<template>
  <div>
    <div id="container"></div>
    <div id="tooltip"></div>

    <!-- <el-button-group class="button-group">
      <el-button type="" icon="" @click="groupOneChange">首页总览</el-button>
      <el-button type="" icon="" @click="groupTwoChange">水文站(5处)</el-button>
      <el-button type="" icon="" @click="groupThreeChange">水质站(9处)</el-button>
      <el-button type="" icon="" @click="groupFourChange">水位站(5处)</el-button>
      <el-button type="" icon="" @click="groupFiveChange">视频站(18处)</el-button>
      <el-button type="" icon="" @click="groupSixChange">雨量频站(4处)</el-button>
    </el-button-group> -->
    <!-- 头部 -->
    <div class="title">
      <div class="biaoti">津市市水系连通及水美乡村建设智慧水利监管平台</div>
      <div class="time">{{ time }}</div>
    </div>
    <div class="center_left" v-if="false">
      <!--降雨量统计  -->
      <div class="jyltj">
        <div class="jyltj_top">
          <div class="yuan"></div>
          <div class="titles">
            <img class="imgs" src="../assets/top_1.png" alt="">
            降雨量统计
          </div>
          <div class="yuan"></div>
        </div>
        <div class="jyltj_center">
          <div class="jyltj_center_item">
            <div class="item_img">
              <img class="imgs" src="../assets/jyltj_3.png" alt="">
              <img class="img" src="/static/map/jyltj_4.png" alt="">
            </div>
            <div class="leiji">当年累积降雨</div>
            <div class="jyl">{{ annalsDataCount >= 0 ? annalsDataCount.toFixed(1) : "-" }}<div class="shuzhi">mm</div>
            </div>
          </div>
          <div class="shux"></div>
          <div class="jyltj_center_item">
            <div class="item_img">
              <img class="imgs" src="../assets/jyltj_2.png" alt="">
              <img class="img" src="/static/map/jyltj_4.png" alt="">
            </div>
            <div class="leiji">当月累积降雨</div>
            <div class="jyl">{{ monthlyDataCount >= 0 ? monthlyDataCount.toFixed(1) : "-" }}<div class="shuzhi">mm</div>
            </div>
          </div>
          <div class="shux"></div>
          <div class="jyltj_center_item">
            <div class="item_img">
              <img class="imgs" src="../assets/jyltj_1.png" alt="">
              <img class="img" src="/static/map/jyltj_4.png" alt="">
            </div>
            <div class="leiji">当日降雨</div>
            <!-- <div class="jyl" >{{ dailyDataCount >= 0 ? dailyDataCount.toFixed(1) : "-" }}<div class="shuzhi">mm</div>
            </div> -->
          </div>
        </div>
        <div class="bottom"></div>
      </div>
      <!--实时水情  -->
      <div class="jyltj">
        <div class="jyltj_top">
          <div class="yuan"></div>
          <div class="titles">
            <img class="imgs" src="../assets/top_2.png" alt="">
            实时水情
          </div>
          <div class="yuan"></div>
        </div>
        <div class="sssq_center">
          <div id="ecmain" style="width: 100%; height: 100%"></div>
        </div>
        <div class="bottom"></div>
      </div>
      <!--当年来水量统计  -->
      <div class="jyltj">
        <div class="jyltj_top">
          <div class="yuan"></div>
          <div class="titles">
            <img class="imgs" src="../assets/top_2.png" alt="">
            当年来水量统计
          </div>
          <div class="yuan"></div>
        </div>
        <div class="lsltj_center">
          <div id="dnlslecmain" style="width: 100%; height: 100%"></div>
        </div>
        <div class="bottom"></div>
      </div>
    </div>
    <div class="center" v-if="false">
      <div class="center_zhuy">
        <div class="center_zhuy_j" @click="tiaozhuan(1)">进入主页面</div>
        <div class="center_zhuy_f" @click="tiaozhuan(2)">返回首页</div>
      </div>
      <div class="center_site">
        <div class="site_item" @click="groupOneChange">
          <div class="site_item_top">
            <img class="img" src="../assets/spjkz01.png" alt="">
            视频站
          </div>
          <div class="site_item_bottom">
            <div class="site_place">{{ spzquantity }}</div><span class="site_font">处</span>
          </div>
        </div>
        <div class="site_item" @click="groupTwoChange">
          <div class="site_item_top">
            <img class="img" src="../assets/swz001.png" alt="">
            水文站
          </div>
          <div class="site_item_bottom">
            <div class="site_place">{{ swzquantity }}</div><span class="site_font">处</span>
          </div>
        </div>
        <div class="site_item" @click="groupThreeChange">
          <div class="site_item_top">
            <img class="img" src="../assets/swz01.png" alt="">
            水位站
          </div>
          <div class="site_item_bottom">
            <div class="site_place">{{ sweizquantity }}</div><span class="site_font">处</span>
          </div>
        </div>
        <div class="site_item" @click="groupFourChange">
          <div class="site_item_top">
            <img class="img" src="../assets/ylz01.png" alt="">
            雨量站
          </div>
          <div class="site_item_bottom">
            <div class="site_place">{{ ylzquantity }}</div><span class="site_font">处</span>
          </div>
        </div>
        <div class="site_item" @click="groupFiveChange">
          <div class="site_item_top">
            <img class="img" src="../assets/szz01.png" alt="">
            水质站
          </div>
          <div class="site_item_bottom">
            <div class="site_place">{{ szzquantity }}</div><span class="site_font">处</span>
          </div>
        </div>
      </div>
    </div>
    <div class="center_right">
      <!--报警信息统计  -->
      <div class="jyltj" v-if="false">
        <div class="jyltj_top">
          <div class="yuan"></div>
          <div class="titles">
            <img class="imgs" src="../assets/top_3.png" alt="">
            报警信息统计
          </div>
          <div class="yuan"></div>
        </div>
        <div class="jyltj_center">
          <div class="jyltj_center_item">
            <div class="items">
              <img class="img" src="../assets/bjxx_1.png" alt="">
              <div class="items_right">
                <div class="items_title">视频监控</div>
                <div class="items_chu">{{ showAlarmInformationData.monitors }}<div class="items_chu_s">处</div>
                </div>
              </div>
            </div>
            <div class="items">
              <img class="img" src="../assets/bjxx_4.png" alt="">
              <div class="items_right">
                <div class="items_title">水位超限</div>
                <div class="items_chu">{{ showAlarmInformationData.waterLevel }} <div class="items_chu_s">处</div>
                </div>
              </div>
            </div>
          </div>
          <div class="jyltj_center_item">
            <div class="items">
              <img class="img" src="../assets/bjxx_3.png" alt="">
              <div class="items_right">
                <div class="items_title">水质超标</div>
                <div class="items_chu">{{ showAlarmInformationData.waterQuality }} <div class="items_chu_s">处</div>
                </div>
              </div>
            </div>
            <div class="items">
              <img class="img" src="../assets/bjxx_2.png" alt="">
              <div class="items_right">
                <div class="items_title">设备故障</div>
                <div class="items_chu">{{ showAlarmInformationData.equipment }} <div class="items_chu_s">处</div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="bottom"></div>
      </div>
      <!--实时水质达标情况  -->
      <div class="jyltj" v-if="false">
        <div class="jyltj_top">
          <div class="yuan"></div>
          <div class="titles">
            <img class="imgs" src="../assets/top_4.png" alt="">
            实时水质达标情况
          </div>
          <div class="yuan"></div>
        </div>
        <div class="ssszdbqk_center">
          <div class="chart-container">
            <div class="chart" ref="chart"></div>
            <!-- 底座背景 -->
            <div class="bg"></div>
          </div>
        </div>
        <div class="bottom"></div>
      </div>
      <!--近六个月水质变化趋势  -->
      <div class="jyltj" v-if="false">
        <div class="jyltj_top">
          <div class="yuan"></div>
          <div class="titles">
            <img class="imgs" src="../assets/top_5.png" alt="">
            近六个月水质变化趋势
          </div>
          <div class="yuan"></div>
        </div>
        <div class="szbhqs_center">
          <div style="display:flex;justify-content: flex-end;width:100%;">
            <div class="inputs">
              <wsselect v-model="waterQualityData" :itemList="divisionData"></wsselect>
            </div>
          </div>
          <div id="szbhqsecmain" style="width: 100%; height: 100%"></div>
        </div>
        <div class="bottom"></div>
      </div>
    </div>
  </div>
</template>


<script>
import * as THREE from "three";
import * as d3 from 'd3';
import * as echarts from "echarts";
import "echarts-gl";
import { getPie3D, getParametricEquation } from '../utils/chat.js'
import BigNumber from "bignumber.js";
import wsselect from "./ws-select.vue";
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js';

const color = ['#0091FF', '#0091FF', '#43BE0F', '#FFD600', '#FF8989', '#D44270']

export default {
  components: {
    wsselect,
  },
  data() {
    return {
      camera: null,
      scene: null,
      renderer: null,
      labelRenderer: null,
      container: null,
      // mesh: null,
      controller: null,
      map: null,
      raycaster: null,
      mouse: null,
      tooltip: null,
      lastPick: null,
      mapEdgeLightObj: {
        mapEdgePoints: [],
        lightOpacityGeometry: null,  // 单独把geometry提出来，动画用

        // 边缘流光参数
        lightSpeed: 3,
        lightCurrentPos: 0,
        lightOpacitys: null,
      },

      // 每个屏幕模型一组
      groupOne: new THREE.Group(),
      groupTwo: new THREE.Group(),
      groupThree: new THREE.Group(),
      groupFour: new THREE.Group(),
      groupFive: new THREE.Group(),//监控组
      groupsw: new THREE.Group(),//水文组
      groupyl: new THREE.Group(),//雨量组
      groupsz: new THREE.Group(),//水质组


      // groupOne 统计信息
      // 视频站数据
      spzData: [],
      cityWaveMeshArr: [],
      cityCylinderMeshArr: [],
      cityMarkerMeshArr: [],
      cityNumMeshArr: [],

      // groupTwo 告警信息
      alarmWaveMeshArr: [],
      alarmCylinderMeshArr: [],
      alarmNameMeshArr: [],

      // groupThree 能源
      energyWaveMeshArr: [],
      energyCylinderMeshArr: [],
      energyNameMeshArr: [],

      // 视频监控 环境
      monitorPostionList: [
        {
          name: '嘉山广场视频站',
          lng: '111.885439',
          lat: '29.55013231',
          status: '在线',
          properties: {
            _centroid: []
          }
        },
        {
          name: '双河口视频站A',
          lng: '111.977466',
          lat: '29.40203',
          status: '在线',
          properties: {
            _centroid: []
          }
        },
        {
          name: '药铺拐视频站',
          lng: '112.0069217',
          lat: '29.34743395',
          status: '在线',
          properties: {
            _centroid: []
          }
        },
        {
          name: '文昌水闸视频站',
          lng: '111.9387986',
          lat: '29.32051792',
          status: '在线',
          properties: {
            _centroid: []
          }
        },
        {
          name: '万寿宫视频站',
          lng: '111.8830008',
          lat: '29.55242749',
          status: '在线',
          properties: {
            _centroid: []
          }
        },
      ],
      monitorWaveMeshArr: [],
      monitorIconMeshArr: [],
      monitorNameMeshArr: [],

      // 城市信息
      mapConfig: {
        deep: 0.2,
      },
      // 摄像机移动位置，初始：0, -5, 1
      cameraPosArr: [
        // {x: 0.0, y: -0.3, z: 1},
        // {x: 5.0, y: 5.0, z: 2},
        // {x: 3.0, y: 3.0, z: 2},
        // {x: 0, y: 5.0, z: 2},
        // {x: -2.0, y: 3.0, z: 1},
        { x: 0, y: -3.0, z: 3.8 },
      ],

      // 数据 - 区县总数量
      dataTotal: [
        {
          name: "淄川区", adcode: "370302", total: 129,
          brief: "经营范围包括凭资质证从事炉窑工程专业承包贰级；工业窑炉热工设备、环保节能设备、机电设备、仪器仪表、电器的制造、销售及调试。"
        },
        {
          name: "张店区", adcode: "370303", total: 89,
          brief: "经营范围包括凭资质证从事炉窑工程专业承包贰级；工业窑炉热工设备、环保节能设备、机电设备、仪器仪表、电器的制造、销售及调试。"
        },
        {
          name: "博山区", adcode: "370304", total: 205,
          brief: "经营范围包括凭资质证从事炉窑工程专业承包贰级；工业窑炉热工设备、环保节能设备、机电设备、仪器仪表、电器的制造、销售及调试。"
        },
        {
          name: "沂源县", adcode: "370323", total: 26,
          brief: "经营范围包括凭资质证从事炉窑工程专业承包贰级；工业窑炉热工设备、环保节能设备、机电设备、仪器仪表、电器的制造、销售及调试。"
        },
        {
          name: "高青县", adcode: "370322", total: 8,
          brief: "经营范围包括凭资质证从事炉窑工程专业承包贰级；工业窑炉热工设备、环保节能设备、机电设备、仪器仪表、电器的制造、销售及调试。"
        },

      ],
      dataAlarm: [
        {
          name: "张店区", adcode: "370303", level: 1,
          type: "压力异常",
          content: "检测到压力过高，超过标准2000Pa",
          company: "窑炉5厂", location: "张店区万山村", tel: "18861899887"
        },
        {
          name: "沂源县", adcode: "370303", level: 1,
          type: "温度异常",
          content: "检测到温度2900­°C，超过标准1200-1800­°C",
          company: "窑炉1厂", location: "沂源县白塔镇南万山村", tel: "13561899812"
        },
        {
          name: "博山区", adcode: "370303", level: 2,
          type: "压力异常",
          content: "检测到压力过高，超过标准2000Pa",
          company: "窑炉2厂", location: "博山区白塔镇南万山村", tel: "14561899817"
        },
        {
          name: "临淄区", adcode: "370303", level: 3,
          type: "用水异常",
          content: "检测到用水异常，超过标准10万吨",
          company: "窑炉3厂", location: "临淄区南万山村", tel: "18061899829"
        },
      ],
      dataEnergy: [
        {
          name: "张店区", adcode: "370303", level: 1,
          type: "用水异常",
          content: "检测到用水异常",
          company: "窑炉5厂", location: "张店区万山村", tel: "18861899887"
        },
        {
          name: "高青县", adcode: "370303", level: 1,
          type: "用电异常",
          content: "检测到用电异常",
          company: "窑炉1厂", location: "沂源县白塔镇南万山村", tel: "13561899812"
        },
        {
          name: "淄川区", adcode: "370303", level: 2,
          type: "用气异常",
          content: "检测到用气异常",
          company: "窑炉2厂", location: "博山区白塔镇南万山村", tel: "14561899817"
        }
      ],
      dataMonitor: [
        {
          name: "临淄区", adcode: "370303", monitor: "监控点一",
          // type: 2,
          content: "正常",
          company: "窑炉5厂", location: "张店区万山村"
        },
        {
          name: "张店区", adcode: "370303", monitor: "监控点二",
          // type: 1,
          content: "正常",
          company: "窑炉1厂", location: "沂源县白塔镇南万山村"
        },
        {
          name: "淄川区", adcode: "370303", monitor: "监控点三",
          // type: 2,
          content: "正常",
          company: "窑炉2厂", location: "博山区白塔镇南万山村"
        }
      ],
      time: "",
      times: "",
      assessChart: "",
      dnlslChart: '',
      // 水质站
      waterQualityData: "",
      divisionData: [],
      historyMyChart: "",
      optionData: [],
      statusChart: null,
      option: {},
      // 日总降水量
      areaDayRainfall: null,
      // 月总降水量
      areaMonthRainfall: null,
      // 年总降水量
      areaYearRainfall: null,
      // 日报数据
      dailyData: [],
      // 月报数据
      monthlyData: [],
      // 年报数据
      annalsData: [],
      // 报警信息统计数据
      showAlarmInformationData: {},
      // 水文站数据
      swzData: [],
      swMonitorWaveMeshArr: [],
      swMonitorIconMeshArr: [],
      swMonitorNameMeshArr: [],
      // 水位站数据
      sweizData: [],
      // 雨量站数据
      ylzData: [],
      ylMonitorWaveMeshArr: [],
      ylMonitorIconMeshArr: [],
      ylMonitorNameMeshArr: [],
      // 水质站数据
      szzData: [],
      szMonitorWaveMeshArr: [],
      szMonitorIconMeshArr: [],
      szMonitorNameMeshArr: [],
      rotatingApertureMesh: "",
      rotatingPointMesh: "",
      uniforms: "",
      clock: "",
      // 各个站点的数量
      spzquantity: "",
      swzquantity: "",
      sweizquantity: "",
      ylzquantity: "",
      szzquantity: "",
    };
  },
  beforeDestroy() {
    clearInterval(this.times);
  },
  created() {
    this.clock = new THREE.Clock();
    this.time = this.getTime()
    // this.times = setInterval(() => {
    //   this.time = this.getTime();
    // }, 1000);
  },
  async mounted() {
    // await this.getSite()
    this.init();
    this.animate();
    this.initGoto()
    this.getRainfallStatistics()
    this.getAlarmInformationStatistics()
    this.getWaterRegime()
    this.dnlslinitGoto()
    this.getAccessTo()
    this.getWaterQualitySite()
    this.szbhqsinitGoto()
    this.RealtimeWaterQualityStandards()
    window.addEventListener('resize', this.onWindowSize)
  },
  watch: {
    waterQualityData: {
      handler(newName, oldName) {
        this.trendForNearlySixMonths();
      },
      deep: true,
    },
  },
  computed: {
    // 计算日降雨量总量
    dailyDataCount() {
      let sum = 0;
      let index = 0;
      if (!this.areaDayRainfall) {
        return
      }
      this.areaDayRainfall.forEach((e) => {
        index++;
        sum = BigNumber(sum).plus(this.dailyData.sum[e]).toString();
      });
      let total = (sum * 1) / index.toFixed(0);
      if (isNaN(total)) {
        total = "";
      }
      return total;
    },
    // 计算月降雨量总量
    monthlyDataCount() {
      let sum = 0;
      let index = 0;
      if (!this.areaMonthRainfall) {
        return
      }
      this.areaMonthRainfall.forEach((e) => {
        index++;
        sum = BigNumber(sum).plus(this.monthlyData.sum[e]).toString();
      });
      return sum / index.toFixed(0);
    },
    // 计算年降雨量总量
    annalsDataCount() {
      let sum = 0;
      let index = 0;
      if (!this.areaYearRainfall) {
        return
      }
      this.areaYearRainfall.forEach((e) => {
        index++;
        sum = BigNumber(sum).plus(this.annalsData.sum[e]).toString();
      });
      return sum / index.toFixed(0);
    },
  },
  methods: {
    tiaozhuan(index) {
      if (index == 1) {
        window.location.href = "http://220.168.231.5:8213/hydraulic_pc/#/index/monitorHome?stater=1"
      } else if (index == 2) {
        window.location.href = "http://220.168.231.5:8213/hydraulic_pc/#/welcome"
      }
    },
    getTime() {
      var myDate = new Date();
      var year = myDate.getFullYear();
      var month = myDate.getMonth() + 1;
      var day = myDate.getDate();
      var hours = myDate.getHours();
      var minutes = myDate.getMinutes();
      var seconds = myDate.getSeconds();
      function timeAdd(m) {
        return m < 10 ? "0" + m : m;
      }
      return (
        timeAdd(year) +
        "-" +
        timeAdd(month) +
        "-" +
        timeAdd(day) +
        " " +
        timeAdd(hours) +
        ":" +
        timeAdd(minutes) +
        ":" +
        timeAdd(seconds)
      );
    },
    // 获取实时水情数据
    getWaterRegime() {
      this.$getMapHttp(
        "show/getWaterRegime"
      ).then((res) => {
        if (res.code == 200) {
          let arr = []
          arr = res.showWaterRegime
          let eachs = []
          arr.forEach(v => {
            eachs.push(v.hydraulicSite.name)
          })
          arr.forEach((e) => {
            eachs[eachs.indexOf(e.hydraulicSite.name)] = {
              product: e.hydraulicSite.name.replace(/水文站/, ""),
              实测水位: e.tz,
              警戒水位: e.hydraulicWaterAlert.warningWater,
            };
          });
          this.assessChart.setOption({
            dataset: {
              source: eachs,
            },
          });
        } else {
          this.$message({
            message: res.msg,
            type: "warning",
          });
        }
      })
    },
    // 渲染实时水情图
    initGoto() {
      // 基于准备好的dom，初始化echarts实例
      this.assessChart = echarts.init(document.getElementById("ecmain"));
      // 绘制图表
      this.assessChart.setOption({
        backgroundColor: "transparent",
        title: {
          // text:'受旱面积(公顷)',
          top: 10,
          //left:'8%',
          textStyle: {
            color: "#FFF",
            fontSize: 15,
          },
        },
        legend: {
          top: 30,
          right: "0%",
          textStyle: {
            color: "#FFF",
          },
        },
        grid: {
          left: "0",
          right: "",
          bottom: "10%",
          top: "17%",
          containLabel: true,
        },
        tooltip: {},
        dataset: {
          dimensions: ["product", "实测水位", "警戒水位"],
          source: [],
        },
        xAxis: {
          type: "category",
          axisLabel: {
            fontSize: 12,
          },
          offset: 15,
          axisLine: {
            lineStyle: {
              color: "#4386CD",
            },
          },
          splitArea: {
            show: true,
            interval: 0,
            areaStyle: {
              color: ['rgba(1, 35, 118, 0.2)', 'rgba(1, 35, 118, 0)'], //这里重点，用于设置颜色的数组，
            }
          }
        },
        yAxis: {
          type: "value",
          name: "单位(m)",
          nameTextStyle: {
            // 设置name样式
            color: "#4386CD",
          },
          axisLabel: {
            textStyle: {
              color: "#4386CD",
            },
          },
          splitLine: {
            lineStyle: {
              type: "dashed",
              color: "#17308A", //刻度线条的颜色
            },
          },
        },
        grid: {
          // height: this.screen > 1400 ? 100 : 80,
          left: "15%", // 左  
          right: "10%", // 右
          top: "40%", // 顶
          bottom: "20%", // 底
        },
        series: [
          {
            type: "bar",
            barWidth: 5, //柱状图宽度
            itemStyle: {
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                { offset: 0, color: "rgba(77,215,207,1)" },
                { offset: 1, color: "rgba(77,215,207,0)" }
              ]),
            },
            emphasis: {
              itemStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  { offset: 0, color: "rgba(77,215,207,1)" },
                  { offset: 1, color: "rgba(77,215,207,0) " }
                ])
              }
            },
            selectedMode: "single",
          },
          {
            type: "bar",
            barWidth: 5, //柱状图宽度
            itemStyle: {
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                { offset: 0, color: "rgba(111,142,180,1)" },
                { offset: 1, color: "rgba(111,142,180,0) " }
              ]),
            },
            emphasis: {
              itemStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  { offset: 0, color: "rgba(111,142,180,1)" },
                  { offset: 1, color: "rgba(111,142,180,0) " }
                ])
              }
            },
            selectedMode: "single",
          },
        ],
      });
    },
    // 获取实时水情数据
    getAccessTo() {
      this.$getMapHttp(
        "show/getAccessToHydrologicStatistics"
      ).then((res) => {
        if (res.code == 200) {
          let arr = []
          arr = res.showAnalyzing
          let eachs = []
          arr.forEach(v => {
            eachs.push(v.name)
          })
          arr.forEach((e) => {
            eachs[eachs.indexOf(e.name)] = {
              product: e.name.replace(/水文站/, ""),
              总来水量: e.qsum,
            };
          });
          this.dnlslChart.setOption({
            dataset: {
              source: eachs,
            },
          });
        } else {
          this.$message({
            message: res.msg,
            type: "warning",
          });
        }
      })
    },
    // 渲染当年来水量统计图
    dnlslinitGoto() {
      // 基于准备好的dom，初始化echarts实例
      this.dnlslChart = echarts.init(document.getElementById("dnlslecmain"));
      let circleList = [
        'image://',
        'image://'
      ]
      // 绘制图表
      this.dnlslChart.setOption({
        backgroundColor: "transparent",
        title: {
          // text:'受旱面积(公顷)',
          top: 10,
          //left:'8%',
          textStyle: {
            color: "#FFF",
            fontSize: 15,
          },
        },
        // legend: {
        //   top: 30,
        //   right: "0%",
        //   textStyle: {
        //     color: "#FFF",
        //   },
        // },
        grid: {
          left: "0",
          right: "",
          bottom: "10%",
          top: "17%",
          containLabel: true,
        },
        tooltip: {},
        // dataset: {
        //   dimensions: ["product","总来水量",],
        //   source: [],
        // },
        xAxis: {
          type: "category",
          axisLabel: {
            fontSize: 12,
          },
          offset: 15,
          axisLine: {
            lineStyle: {
              color: "#4386CD",
            },
          },
          splitArea: {
            show: true,
            interval: 0,
            areaStyle: {
              color: ['rgba(1, 35, 118, 0.2)', 'rgba(1, 35, 118, 0)'], //这里重点，用于设置颜色的数组，
            }
          }
        },
        yAxis: {
          type: "value",
          name: "万m³",
          nameTextStyle: {
            // 设置name样式
            color: "#4386CD",
          },
          axisLabel: {
            textStyle: {
              color: "#4386CD",
            },
          },
          splitLine: {
            lineStyle: {
              type: "dashed",
              color: "#17308A", //刻度线条的颜色
            },
          },
        },
        grid: {
          // height: this.screen > 1400 ? 100 : 80,
          left: "20%", // 左  
          right: "8%", // 右
          top: "20%", // 顶
          bottom: "20%", // 底
        },
        series: [
          {
            type: "bar",
            barWidth: 5, //柱状图宽度
            itemStyle: {
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                { offset: 0, color: "rgba(77,215,207,1)" },
                { offset: 1, color: "rgba(77,215,207,0)" }
              ]),
            },
            emphasis: {
              itemStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  { offset: 0, color: "rgba(77,215,207,1)" },
                  { offset: 1, color: "rgba(77,215,207,0) " }
                ])
              },
            },
            selectedMode: "single",
          },
          {
            name: '总来水量',
            type: 'pictorialBar',
            symbol: function (params, value) {
              // 设置图片
              if (params >= 50) return circleList[1]
              return circleList[1]
            },
            symbolPosition: 'end',
            symbolSize: [30, 30],
            symbolOffset: [0, -15],
          }
        ],
      });
    },
    // 获取水质站点
    getWaterQualitySite() {
      this.$getMapHttp(
        "show/getWaterQualitySite"
      ).then((res) => {
        if (res.code == 200) {
          let arr = []
          arr = res.siteList
          let divisionData = []
          arr.forEach(v => {
            divisionData.push({ label: v.name, value: v.telemetryaddress })
          })
          this.divisionData = divisionData
          this.waterQualityData = divisionData[0].value
          this.trendForNearlySixMonths()
        } else {
          this.$message({
            message: res.msg,
            type: "warning",
          });
        }
      })
    },
    // 渲染近六个月水质变化趋势图
    szbhqsinitGoto() {
      this.historyMyChart = echarts.init(document.getElementById("szbhqsecmain"));
      this.historyMyChart.setOption({
        xAxis: {
          type: "category",
          offset: 20,
          axisLine: {
            lineStyle: {
              color: "#4386CD",
            },
          },
          axisLabel: {
            fontSize: 8,
          }
        },
        grid: {
          left: "10%", // 左  
          right: "8%", // 右
          top: "10%", // 顶
          bottom: "30%", // 底
        },
        yAxis: {
          data: ["Ⅰ", "Ⅱ", "Ⅲ", "Ⅳ", "Ⅴ", "劣Ⅴ"],
          axisLine: {
            lineStyle: {
              color: "#4386CD",
            },
          },
          splitLine: {
            lineStyle: {
              type: "dashed",
              color: "#17308A", //刻度线条的颜色
            },
          },
          axisLabel: {
            fontSize: 10,
          }
        },
        tooltip: {
          trigger: "axis",
        },
        legend: {
          right: "10%",
          show: false,
          textStyle: {
            color: "white",
          },
        },
      });
    },
    // 获取近六个月水质变化趋势数据
    trendForNearlySixMonths() {
      this.$getMapHttp("show/waterQualityChangeTrendForNearlySixMonths", {
        telemetryAddress: this.waterQualityData
      }).then((res) => {
        if (res.code == 200) {
          let arr = []
          arr = res.showWaterQualitySixMonths
          let echarsTime = []
          let echarsData = []
          arr.forEach(v => {
            echarsTime.push(v.updatetime.slice(0, 7))
            echarsData.push(v.waterQualityGrade)
          })
          let echarsList = []
          echarsList.push({
            data: echarsData, name: arr[0].hydraulicSite.name, type: "line", symbolSize: 28,
            symbol: "image://"
          })
          this.historyMyChart.setOption({
            xAxis: {
              data: echarsTime,
            },
            legend: {
              // data:name
            },
            series: echarsList,
          });
        } else {
          this.$message({
            message: res.msg,
            type: "warning",
          });
        }
      })
    },
    setLabel() {
      this.optionData.forEach((item, index) => {
        item.itemStyle = { color: color[index] }
        item.label = {
          normal: {
            show: true,
            color: color[index],
            formatter: [
              '{b|{b}}',
              '{d|{d}%}'
            ].join(''), // 用来换行
            rich: {
              b: {
                color: '#fff',
                lineHeight: 25,
                align: 'left'
              },
              c: {
                fontSize: 22,
                color: '#fff',
                textShadowColor: '#1c90a6',
                textShadowOffsetX: 0,
                textShadowOffsetY: 2,
                textShadowBlur: 5
              },
              d: {
                color: color[index],
                align: 'left'
              }
            }
          }
        }
        item.labelLine = {
          normal: {
            lineStyle: {
              width: 1,
              color: 'rgba(255,255,255,0.7)'
            }
          }
        }
      })
    },
    // 图表初始化
    initChart() {
      this.statusChart = echarts.init(this.$refs.chart)
      // 传入数据生成 option, 构建3d饼状图, 参数工具文件已经备注的很详细
      this.option = getPie3D(this.optionData, 0.8, 240, 28, 10, 0.5)
      this.statusChart.setOption(this.option)
      // 是否需要label指引线，如果要就添加一个透明的2d饼状图并调整角度使得labelLine和3d的饼状图对齐，并再次setOption
      this.option.series.push({
        name: '实时水情', //自己根据场景修改
        backgroundColor: 'transparent',
        type: 'pie',
        label: {
          opacity: 1,
          fontSize: 13,
          lineHeight: 20,
          normal: {
            position: "inner"
          }
        },
        labelLine: {
          normal: {
            show: false
          }
        },
        startAngle: -70, // 起始角度，支持范围[0, 360]。
        clockwise: false, // 饼图的扇区是否是顺时针排布。上述这两项配置主要是为了对齐3d的样式
        radius: ['20%', '50%'],
        center: ['50%', '50%'],
        data: this.optionData,
        itemStyle: {
          opacity: 0  //这里必须是0，不然2d的图会覆盖在表面
        }
      })
      this.statusChart.setOption(this.option)
      this.bindListen(this.statusChart)
    },
    // 监听鼠标事件，实现饼图选中效果（单选），近似实现高亮（放大）效果。
    // optionName是防止有多个图表进行定向option传递，单个图表可以不传，默认是opiton
    bindListen(myChart, optionName = 'option') {
      let selectedIndex = ''
      let hoveredIndex = ''
      // 监听点击事件，实现选中效果（单选）
      myChart.on('click', (params) => {
        // 从 option.series 中读取重新渲染扇形所需的参数，将是否选中取反。
        const isSelected = !this[optionName].series[params.seriesIndex].pieStatus.selected
        const isHovered = this[optionName].series[params.seriesIndex].pieStatus.hovered
        const k = this[optionName].series[params.seriesIndex].pieStatus.k
        const startRatio = this[optionName].series[params.seriesIndex].pieData.startRatio
        const endRatio = this[optionName].series[params.seriesIndex].pieData.endRatio
        // 如果之前选中过其他扇形，将其取消选中（对 option 更新）
        if (selectedIndex !== '' && selectedIndex !== params.seriesIndex) {
          this[optionName].series[selectedIndex].parametricEquation = getParametricEquation(
            this[optionName].series[selectedIndex].pieData.startRatio,
            this[optionName].series[selectedIndex].pieData.endRatio, false, false, k,
            this[optionName].series[selectedIndex].pieData.value
          )
          this[optionName].series[selectedIndex].pieStatus.selected = false
        }
        // 对当前点击的扇形，执行选中/取消选中操作（对 option 更新）
        this[optionName].series[params.seriesIndex].parametricEquation = getParametricEquation(
          startRatio,
          endRatio,
          isSelected,
          isHovered,
          k,
          this[optionName].series[params.seriesIndex].pieData.value
        )
        this[optionName].series[params.seriesIndex].pieStatus.selected = isSelected
        // 如果本次是选中操作，记录上次选中的扇形对应的系列号 seriesIndex
        selectedIndex = isSelected ? params.seriesIndex : null
        // 使用更新后的 option，渲染图表
        myChart.setOption(this[optionName])
      })
      // 监听 mouseover，近似实现高亮（放大）效果
      myChart.on('mouseover', (params) => {
        // 准备重新渲染扇形所需的参数
        let isSelected
        let isHovered
        let startRatio
        let endRatio
        let k
        // 如果触发 mouseover 的扇形当前已高亮，则不做操作
        if (hoveredIndex === params.seriesIndex) {
          // 否则进行高亮及必要的取消高亮操作
        } else {
          // 如果当前有高亮的扇形，取消其高亮状态（对 option 更新）
          if (hoveredIndex !== '') {
            // 从 option.series 中读取重新渲染扇形所需的参数，将是否高亮设置为 false。
            isSelected = this[optionName].series[hoveredIndex].pieStatus.selected
            isHovered = false
            startRatio = this[optionName].series[hoveredIndex].pieData.startRatio
            endRatio = this[optionName].series[hoveredIndex].pieData.endRatio
            k = this[optionName].series[hoveredIndex].pieStatus.k
            // 对当前点击的扇形，执行取消高亮操作（对 option 更新）
            this[optionName].series[
              hoveredIndex
            ].parametricEquation = getParametricEquation(
              startRatio,
              endRatio,
              isSelected,
              isHovered,
              k,
              this[optionName].series[hoveredIndex].pieData.value
            )
            this[optionName].series[hoveredIndex].pieStatus.hovered = isHovered
            // 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
            hoveredIndex = ''
          }
          // 如果触发 mouseover 的扇形不是透明圆环，将其高亮（对 option 更新）
          if (
            params.seriesName !== 'mouseoutSeries' &&
            params.seriesName !== 'pie2d'
          ) {
            // 从 option.series 中读取重新渲染扇形所需的参数，将是否高亮设置为 true。
            isSelected = this[optionName].series[params.seriesIndex].pieStatus.selected
            isHovered = true
            startRatio = this[optionName].series[params.seriesIndex].pieData.startRatio
            endRatio = this[optionName].series[params.seriesIndex].pieData.endRatio
            k = this[optionName].series[params.seriesIndex].pieStatus.k
            // 对当前点击的扇形，执行高亮操作（对 option 更新）
            this[optionName].series[params.seriesIndex].parametricEquation = getParametricEquation(
              startRatio,
              endRatio,
              isSelected,
              isHovered,
              k,
              this[optionName].series[params.seriesIndex].pieData.value + 5
            )
            this[optionName].series[params.seriesIndex].pieStatus.hovered = isHovered
            // 记录上次高亮的扇形对应的系列号 seriesIndex
            hoveredIndex = params.seriesIndex
          }
          // 使用更新后的 option，渲染图表
          myChart.setOption(this[optionName])
        }
      })
      // 修正取消高亮失败的 bug
      myChart.on('globalout', () => {
        // 准备重新渲染扇形所需的参数
        let isSelected
        let isHovered
        let startRatio
        let endRatio
        let k
        if (hoveredIndex !== '') {
          // 从 option.series 中读取重新渲染扇形所需的参数，将是否高亮设置为 true。
          isSelected = this[optionName].series[hoveredIndex].pieStatus.selected
          isHovered = false
          k = this[optionName].series[hoveredIndex].pieStatus.k
          startRatio = this[optionName].series[hoveredIndex].pieData.startRatio
          endRatio = this[optionName].series[hoveredIndex].pieData.endRatio
          // 对当前点击的扇形，执行取消高亮操作（对 option 更新）
          this[optionName].series[hoveredIndex].parametricEquation = getParametricEquation(
            startRatio,
            endRatio,
            isSelected,
            isHovered,
            k,
            this[optionName].series[hoveredIndex].pieData.value
          )
          this[optionName].series[hoveredIndex].pieStatus.hovered = isHovered
          // 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
          hoveredIndex = ''
        }
        // 使用更新后的 option，渲染图表
        myChart.setOption(this[optionName])
      })
    },
    // 获取实时水质达标情况数据
    RealtimeWaterQualityStandards() {
      this.$getMapHttp("show/accessToRealtimeWaterQualityStandards").then((res) => {
        if (res.code == 200) {
          let obj = {}
          let arr = []
          obj = res.showWaterQuality
          for (var key in obj) {
            if (key != "sum") {
              arr.push({ name: key, value: obj[key] })
            }
          }
          this.optionData = arr
          // 初始化环形图label
          this.setLabel()
          this.initChart()
        } else {
          this.$message({
            message: res.msg,
            type: "warning",
          });
        }
      })
    },
    // 获取降雨量统计数据
    getRainfallStatistics() {
      this.$getMapHttp("show/getRainfallStatistics").then((res) => {
        if (res.code == 200) {
          let keys = [];
          if (res.showRainFall.dayRainFall.rainStatements.length > 0) {
            for (let key in res.showRainFall.dayRainFall.rainStatements[0]) {
              if (key != "updatetime") {
                keys.push(key);
              }
            }
          }
          this.areaDayRainfall = keys;
          this.dailyData = res.showRainFall.dayRainFall;

          let keys2 = [];
          if (res.showRainFall.monthRainFall.rainStatements.length > 0) {
            for (let key in res.showRainFall.dayRainFall.rainStatements[0]) {
              if (key != "updatetime") {
                keys2.push(key);
              }
            }
          }
          this.areaMonthRainfall = keys2;
          this.monthlyData = res.showRainFall.monthRainFall

          let keys3 = [];
          if (res.showRainFall.yearRainFall.rainStatements.length > 0) {
            for (let key in res.showRainFall.dayRainFall.rainStatements[0]) {
              if (key != "updatetime") {
                keys3.push(key);
              }
            }
          }
          this.areaYearRainfall = keys3;
          this.annalsData = res.showRainFall.yearRainFall;

        } else {
          this.$message({
            message: res.msg,
            type: "warning",
          });
        }
      })
    },
    // 获取报警信息统计数据
    getAlarmInformationStatistics() {
      this.$getMapHttp("show/getAlarmInformationStatistics").then((res) => {
        if (res.code == 200) {
          this.showAlarmInformationData = res.showAlarmInformation
        } else {
          this.$message({
            message: res.msg,
            type: "warning",
          });
        }
      })
    },
    // 获取总站点信息
    async getSite() {
      await this.$getMapHttp("show/getSite").then((res) => {
        if (res.code == 200) {
          this.spzquantity = res.showSite.shiPingZhan.length
          this.swzquantity = res.showSite.shuiWenZhan.length
          this.sweizquantity = res.showSite.shuiWeiZhan.length
          this.ylzquantity = res.showSite.yuLiangZhan.length
          this.szzquantity = res.showSite.ziDongShuiZhiZhan.length
          res.showSite.shiPingZhan.map(v => {
            { { } }
            v.properties = { _centroid: [] }
            return v
          })
          this.spzData = res.showSite.shiPingZhan
          res.showSite.shuiWenZhan.map(v => {
            v.properties = { _centroid: [] }
            return v
          })
          this.swzData = res.showSite.shuiWenZhan
          res.showSite.yuLiangZhan.map(v => {
            v.properties = { _centroid: [] }
            return v
          })
          this.ylzData = res.showSite.yuLiangZhan
          let arr = []
          // res.showSite.renGongShuiZhiZhan.forEach(v=>{
          //   arr.push(v)
          // })
          res.showSite.ziDongShuiZhiZhan.forEach(v => {
            arr.push(v)
          })
          arr.map(v => {
            v.properties = { _centroid: [] }
            return v
          })
          this.szzData = arr
        } else {
          this.$message({
            message: res.msg,
            type: "warning",
          });
        }
      })
    },
    //初始化
    init() {
      this.container = document.getElementById("container");
      this.setScene();
      this.setCamera();
      this.setRenderer();  // 创建渲染器对象
      this.setController();  // 创建控件对象
      this.addHelper();
      this.addSpace();
      this.loadMapData();
      this.setEarth();
      this.setxxuan();
      this.setRaycaster();
      this.setLight();
    },

    setScene() {
      //  创建场景对象Scene
      this.scene = new THREE.Scene();
    },

    // 背景圈旋转
    setxxuan() {

    },

    setCamera() {
      // 第二参数就是 长度和宽度比 默认采用浏览器  返回以像素为单位的窗口的内部宽度和高度
      this.camera = new THREE.PerspectiveCamera(
        75,
        window.innerWidth / window.innerHeight,
        0.1,
        500
      );

      this.camera.position.set(0, -5, 1);  // 0, -5, 1
      this.camera.lookAt(new THREE.Vector3(0, 0, 0));  // 0, 0, 0 this.scene.position
    },

    setRenderer() {
      this.renderer = new THREE.WebGLRenderer({
        antialias: true,
        // logarithmicDepthBuffer: true,  // 是否使用对数深度缓存
      });
      this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
      this.renderer.setPixelRatio(window.devicePixelRatio);
      // this.renderer.sortObjects = false;  // 是否需要对对象排序
      this.container.appendChild(this.renderer.domElement);


      this.labelRenderer = new CSS2DRenderer();
      this.labelRenderer.setSize(this.container.clientWidth, this.container.clientHeight);
      this.labelRenderer.domElement.style.position = 'absolute';
      this.labelRenderer.domElement.style.top = 0;
      this.container.appendChild(this.labelRenderer.domElement);
    },

    setController() {
      this.controller = new OrbitControls(this.camera, this.labelRenderer.domElement);
      this.controller.minDistance = 2;
      this.controller.maxDistance = 5.5  // 5.5

      // 阻尼（惯性）
      // this.controller.enableDamping = true;
      // this.controller.dampingFactor = 0.04;

      this.controller.minAzimuthAngle = -Math.PI / 4;
      this.controller.maxAzimuthAngle = Math.PI / 4;

      this.controller.minPolarAngle = 1;
      this.controller.maxPolarAngle = Math.PI - 0.1;

      // 修改相机的lookAt是不会影响THREE.OrbitControls的target的
      // this.controller.target = new THREE.Vector3(0, -5, 2); 

    },

    // 辅助线
    addHelper() {
      // let helper = new THREE.CameraHelper(this.camera);
      // this.scene.add(helper);

      //轴辅助 （每一个轴的长度）
      let axisHelper = new THREE.AxisHelper(150);  // 红线是X轴，绿线是Y轴，蓝线是Z轴
      // this.scene.add(axisHelper);

      let gridHelper = new THREE.GridHelper(100, 30, 0x2C2C2C, 0x888888);
      // this.scene.add(gridHelper);        
    },

    // 宇宙模型
    addSpace() {
      let textures = [
        new THREE.TextureLoader().load('/static/map/texture/space2/4.jpg'), // right
        new THREE.TextureLoader().load('/static/map/texture/space2/2.jpg'), // left
        new THREE.TextureLoader().load('/static/map/texture/space2/1.jpg'), // top
        new THREE.TextureLoader().load('/static/map/texture/space2/6.jpg'), // bottom
        new THREE.TextureLoader().load('/static/map/texture/space2/3.jpg'), // back
        new THREE.TextureLoader().load('/static/map/texture/space2/5.jpg') // front
      ];
      let materials = [
        new THREE.MeshBasicMaterial({ map: textures[0], side: THREE.BackSide, precision: "highp" }),
        new THREE.MeshBasicMaterial({ map: textures[1], side: THREE.BackSide, precision: "highp" }),
        new THREE.MeshBasicMaterial({ map: textures[2], side: THREE.BackSide, precision: "highp" }),
        new THREE.MeshBasicMaterial({ map: textures[3], side: THREE.BackSide, precision: "highp" }),
        new THREE.MeshBasicMaterial({ map: textures[4], side: THREE.BackSide, precision: "highp" }),
        new THREE.MeshBasicMaterial({ map: textures[5], side: THREE.BackSide, precision: "highp" }),
      ];
      const geometry = new THREE.BoxGeometry(300, 300, 300);
      let mesh = new THREE.Mesh(geometry, materials);
      // console.log(mesh);

      // const position = mesh.geometry.attributes.position;
      // const vector = new THREE.Vector3();
      // for ( let i = 0, l = position.count; i < l; i ++ ){
      //     vector.fromBufferAttribute( position, i );
      //     vector.applyMatrix4(mesh.matrixWorld);
      //     console.log(vector);
      // }

      // for (var i = 0, l = mesh.geometry.attributes.position.length; i < l; i++) {
      //   var vertex = mesh.geometry.vertices[i];
      //   vertex.normalize();
      //   vertex.multiplyScalar(550);
      // }     

      mesh.scale.x = -1;
      this.scene.add(mesh);

    },

    setLight() {
      const ambientLight = new THREE.AmbientLight(0x7af4ff, 1.2);
      this.scene.add(ambientLight);
      // // 平行光
      const directionalLight = new THREE.DirectionalLight(0xffffff, 1.0);
      this.scene.add(directionalLight);

      // 聚光光源 - 照模型
      // const spotLight = new THREE.SpotLight(0xffffff, 0.9);
      // spotLight.position.set(1, -4, 4);
      // spotLight.castShadow = true;
      // this.scene.add(spotLight);
      // 聚光光源辅助线
      // const spotLightHelper = new THREE.SpotLightHelper(spotLight);
      // this.scene.add(spotLightHelper);

      // 点光源 - 照模型
      const test = new THREE.PointLight("#ffffff", 1.8, 20);
      test.position.set(1, 0, 7);
      this.scene.add(test);
      const testHelperMap = new THREE.PointLightHelper(test);
      this.scene.add(testHelperMap);

      // 点光源 - 蓝色照地球
      // const pointLightMap = new THREE.PointLight("#4161ff", 1.4, 20);
      // pointLightMap.position.set(0, 7, 3);
      // this.scene.add(pointLightMap);
      // const spotLightHelperMap = new THREE.PointLightHelper(pointLightMap);
      // this.scene.add(spotLightHelperMap);
    },

    // 加载地图数据
    loadMapData() {
      const loader = new THREE.FileLoader();
      loader.load("/static/map/json/jinshishi.json", data => {
        const jsondata = JSON.parse(data);
        this.addMapGeometry(jsondata);
      })
    },

    // 地图模型
    addMapGeometry(jsondata) {
      // 初始化一个地图对象
      this.map = new THREE.Object3D();
      // 墨卡托投影转换
      const projection = d3
        .geoMercator()
        .center([111.86842, 29.49963])   // 地图中心 111.86842,29.49963
        .scale(500)
        .translate([-0.2, 0.2]);  // 根据地球贴图做轻微调整

      jsondata.features.forEach((elem) => {
        // 定一个省份3D对象
        const province = new THREE.Object3D();
        // 每个的 坐标 数组
        const coordinates = elem.geometry.coordinates;
        // 循环坐标数组
        coordinates.forEach((multiPolygon) => {
          multiPolygon.forEach((polygon) => {
            const shape = new THREE.Shape();
            const lineMaterial = new THREE.LineBasicMaterial({
              color: '#ffffff',
              // linewidth: 1,
              // linecap: 'round', //ignored by WebGLRenderer
              // linejoin:  'round' //ignored by WebGLRenderer                
            });
            // const lineGeometry = new THREE.Geometry();
            // for (let i = 0; i < polygon.length; i++) {
            //   const [x, y] = projection(polygon[i]);
            //   if (i === 0) {
            //     shape.moveTo(x, -y);
            //   }
            //   shape.lineTo(x, -y);
            //   lineGeometry.vertices.push(new THREE.Vector3(x, -y, 3));
            // }
            const lineGeometry = new THREE.BufferGeometry();
            const pointsArray = new Array();
            for (let i = 0; i < polygon.length; i++) {
              const [x, y] = projection(polygon[i]);
              if (i === 0) {
                shape.moveTo(x, -y);
              }
              shape.lineTo(x, -y);
              pointsArray.push(new THREE.Vector3(x, -y, this.mapConfig.deep));
              console.log(pointsArray)
              // 做边缘流光效果，把所有点保存下来
              this.mapEdgeLightObj.mapEdgePoints.push([x, -y, this.mapConfig.deep]);
            }
            // console.log(pointsArray);
            lineGeometry.setFromPoints(pointsArray);

            const extrudeSettings = {
              depth: this.mapConfig.deep,
              bevelEnabled: false,  // 对挤出的形状应用是否斜角
            };

            const geometry = new THREE.ExtrudeGeometry(
              shape,
              extrudeSettings
            );
            //地图表面颜色
            //color、opacity、shading、blending、depthTest、depthWrite、wireframe、wireframeLinewidth、wireframeLinecap、wireframeLineJoin、vertexColors
            //颜色、不透明度、着色、混合、深度测试、深度写入、线框、线框线宽、线框线帽、线框线条连接、顶点颜色
            const bumpTexture = new THREE.TextureLoader().load('/static/map/texture/222.jpg');
            const texture = new THREE.TextureLoader().load('/static/map/texture/222.jpg');
            const bgcolor = new THREE.TextureLoader().load('/static/map/texture/333.jpg');
            // 设置阵列
            texture.wrapS = THREE.RepeatWrapping;
            texture.wrapT = THREE.RepeatWrapping;
            // uv两个方向纹理重复数量
            texture.repeat.set(1, 1);
            let material = new THREE.MeshBasicMaterial({
              // material.map = texture;
              // const material = new THREE.MeshPhongMaterial({
              // color: '#4161ff',
              // transparent: true,
              // opacity: 0.4,
              // side: THREE.FrontSide,
              //普通纹理贴图
              map: texture,
              //凹凸纹理
              // bumpMap:bumpTexture,
              // bumpScale: 0.05,
              // specularMap: texture,
              // specular: 0xffffff,
              // shininess: 1,
              // color: "#000000", 
              // depthTest: true,
            });
            //地图侧面颜色
            const material1 = new THREE.MeshLambertMaterial({
              color: '#336350',
              transparent: true,
              opacity: 0.7,
              side: THREE.FrontSide,
              wireframe: true,
              map: bgcolor,
            });
            const mesh = new THREE.Mesh(geometry, [material, material1]);
            const line = new THREE.Line(lineGeometry, lineMaterial);
            console.log(line,7887)
            // 将省份的属性 加进来
            province.properties = elem.properties;

            // 将城市信息放到模型中，后续做动画用
            if (elem.properties.centroid) {
              const [x, y] = projection(elem.properties.centroid)  // uv映射坐标
              province.properties._centroid = [x, y]
            }
            console.log(this.spzData, "数据");
            //将监控信息放到模型中，后续做动画用
            this.spzData.forEach(element => {
              const [x, y] = projection([element.longitude, element.latitude])  // uv映射坐标
              element.properties._centroid = [x, y]

            });
            //将水文站信息放到模型中，后续做动画用
            this.swzData.forEach(element => {
              const [x, y] = projection([element.longitude, element.latitude])  // uv映射坐标
              element.properties._centroid = [x, y]

            });
            //将雨量站信息放到模型中，后续做动画用
            this.ylzData.forEach(element => {
              const [x, y] = projection([element.longitude, element.latitude])  // uv映射坐标
              element.properties._centroid = [x, y]

            });
            //将水质站信息放到模型中，后续做动画用
            this.szzData.forEach(element => {
              const [x, y] = projection([element.longitude, element.latitude])  // uv映射坐标
              element.properties._centroid = [x, y]

            });
            province.add(mesh);
            province.add(line);
          })
        })
        // province.scale.set(5, 5, 0);
        // province.position.set(0, 0, 0);
        // console.log(province);
        this.map.add(province);
      })
      this.setMapEdgeLight();
      this.setMapName();
      this.scene.add(this.map);
      console.log(this.mapEdgeLightObj.mapEdgePoints," 02201")
      const material = this.createOpacityWallMat({ height: 0.5, speed: 5 });
      const wallMesh = this.creatWallByPath({
        path:this.mapEdgeLightObj.mapEdgePoints,
        material,
        height: 0.5,
      });
      // 动画
      // animationList.push(() => {
      //   wallMesh.material.uniforms.time.value +=
      //     clock.getDelta() * wallMesh.material.uniforms.speed.value;
      // });
      this.scene.add(wallMesh);
      this.scene.add(material);
      // 获取数据后，加载模型
      this.getResponseData();

    },
    creatWallByPath({
      height =2,
      path = [],
      material,
      expand = true,
    }) {
      let verticesByTwo = null;
      // 1.处理路径数据  每两个顶点为为一组
      if (expand) {
        // 1.1向y方向拉伸顶点
        console.log(path)
        verticesByTwo = path.reduce((arr, [x, y, z]) => {
          return arr.concat([
            [
              [x, y, z],
              [x, y, z + height],
            ],
          ]);
        }, []);
      } else {
        // 1.2 已经处理好路径数据
        verticesByTwo = path;
      }
      // 2.解析需要渲染的四边形 每4个顶点为一组
      const verticesByFour = verticesByTwo.reduce((arr, item, i) => {
        if (i === verticesByTwo.length - 1) return arr;
        return arr.concat([[item, verticesByTwo[i + 1]]]);
      }, []);
      // 3.将四边形面转换为需要渲染的三顶点面
      const verticesByThree = verticesByFour.reduce((arr, item) => {
        const [[point1, point2], [point3, point4]] = item;
        return arr.concat(
          ...point2,
          ...point1,
          ...point4,
          ...point1,
          ...point3,
          ...point4
        );
      }, []);
      const geometry = new THREE.BufferGeometry();
      // 4. 设置position
      const vertices = new Float32Array(verticesByThree);
      geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
      // 5. 设置uv 6个点为一个周期 [0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1]

      // 5.1 以18个顶点为单位分组
      const pointsGroupBy18 = new Array(verticesByThree.length / 3 / 6)
        .fill(0)
        .map((item, i) => {
          return verticesByThree.slice(i * 3 * 6, (i + 1) * 3 * 6);
        });
      // 5.2 按uv周期分组
      const pointsGroupBy63 = pointsGroupBy18.map((item, i) => {
        return new Array(item.length / 3)
          .fill(0)
          .map((it, i) => item.slice(i * 3, (i + 1) * 3));
      });
      // 5.3根据BoundingBox确定uv平铺范围
      geometry.computeBoundingBox();
      const { min, max } = geometry.boundingBox;
      const rangeX = max.x - min.x;
      const uvs = [].concat(
        ...pointsGroupBy63.map((item) => {
          const point0 = item[0];
          const point5 = item[5];
          const distance =
            new THREE.Vector3(...point0).distanceTo(new THREE.Vector3(...point5)) /
            (rangeX / 10);
          return [0, 1, 0, 0, distance, 1, 0, 0, distance, 0, distance, 1];
        })
      );
      geometry.setAttribute(
        "uv",
        new THREE.BufferAttribute(new Float32Array(uvs), 2)
      );
      // 更新法线
      // geometry.computeVertexNormals();
      const meshMat =
        material ||
        new THREE.MeshBasicMaterial({
          color: 0x00ffff,
          side: THREE.DoubleSide,
        });
      return new THREE.Mesh(geometry, meshMat);
    },
    createOpacityWallMat({
      height = 10,
      color = "#ffffff",
      opacity = 0.1,
      speed = 1,
    }) {
      // 顶点着色器
      const vertexShader = `
          uniform vec3 u_color;

          uniform float time;
          uniform float u_height;
          varying float v_opacity;

          void main() {
              vec3 vPosition = position;
              v_opacity = mix(1.0, 0.0, position.y / u_height * 1.0) * (1.0 + sin(time) * 0.5);
              gl_Position = projectionMatrix * modelViewMatrix * vec4(vPosition, 1);
          }
       `;
        // 片元着色器
        const fragmentShader = `
          uniform vec3 u_color;
          uniform float u_opacity;
          varying float v_opacity;
          void main() {
              gl_FragColor = vec4(u_color, v_opacity * u_opacity);
          }
        `;

        return new THREE.ShaderMaterial({
          uniforms: {
            u_height: {
              value: height,
            },
            u_opacity: {
              value: opacity,
            },
            u_color: {
              value: new THREE.Color(color),
            },
            time: {
              value: 0,
            },
            speed: {
              value: speed,
            },
          },
          lights:false,
          transparent: true,
          depthWrite: false,
          depthTest: false,
          // side: THREE.DoubleSide,
          vertexShader: vertexShader,
          fragmentShader: fragmentShader,
        });
    },
    // 地图边缘流光效果
    setMapEdgeLight() {
      // console.log(this.mapEdgeLightObj.mapEdgePoints);
      let positions = new Float32Array(this.mapEdgeLightObj.mapEdgePoints.flat(1));  // 数组深度遍历扁平化
      console.log(positions,8494);
      this.mapEdgeLightObj.lightOpacityGeometry = new THREE.BufferGeometry();
      // 设置顶点
      this.mapEdgeLightObj.lightOpacityGeometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));
      // 设置 粒子透明度为 0
      this.mapEdgeLightObj.lightOpacitys = new Float32Array(positions.length).map(() => 0);
      this.mapEdgeLightObj.lightOpacityGeometry.setAttribute("aOpacity", new THREE.BufferAttribute(this.mapEdgeLightObj.lightOpacitys, 1));

      // 顶点着色器
      const vertexShader = `
          attribute float aOpacity;
          uniform float uSize;
          varying float vOpacity;

          void main(){
              gl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0);
              gl_PointSize = uSize;

              vOpacity=aOpacity;
          }
          `
      // 片段着色器
      const fragmentShader = `
          varying float vOpacity;
          uniform vec3 uColor;

          float invert(float n){
              return 1.-n;
          }

          void main(){
            if(vOpacity <=0.2){
                discard;
            }
            vec2 uv=vec2(gl_PointCoord.x,invert(gl_PointCoord.y));
            vec2 cUv=2.*uv-1.;
            vec4 color=vec4(1./length(cUv));
            color*=vOpacity;
            color.rgb*=uColor;
            gl_FragColor=color;
          }
          `

      const material = new THREE.ShaderMaterial({
        vertexShader: vertexShader,
        fragmentShader: fragmentShader,
        transparent: true, // 设置透明
        // blending: THREE.AdditiveBlending,
        uniforms: {
          uSize: {
            value: 5.0
          },
          uColor: {
            value: new THREE.Color("#ffffff")  // 光点颜色 fffb85
          }
        }
      })
      // material.blending = THREE.AdditiveBlending;
      const opacityPointsMesh = new THREE.Points(this.mapEdgeLightObj.lightOpacityGeometry, material);
      this.scene.add(opacityPointsMesh);

    },

    // 地球贴图纹理
    setEarth() {
      // const geometry = new THREE.PlaneGeometry(14.0, 8.0);
      // const texture = new THREE.TextureLoader().load('/static/map/texture/index_bg.png');
      // const bumpTexture = new THREE.TextureLoader().load('/static/map/texture/index_bg.png');
      // // texture.wrapS = THREE.RepeatWrapping;  // 质地.包裹
      // // texture.wrapT = THREE.RepeatWrapping;

      // const material = new THREE.MeshPhongMaterial({
      //   map: texture,  // 贴图
      //   bumpMap: bumpTexture,
      //   bumpScale: 0.05,
      //   // specularMap: texture,
      //   // specular: 0xffffff,
      //   // shininess: 1,
      //   // color: "#000000", 
      //   side: THREE.FrontSide} 
      // );
      // const earthPlane = new THREE.Mesh(geometry, material);
      // this.scene.add(earthPlane);
      let texture = new THREE.TextureLoader().load("/static/map/texture/地板背景.png")
      const geometry2 = new THREE.CircleGeometry(3, 1000);
      this.uniforms = {
        iTime: { value: 0.1 },
        colorTexture: { value: texture }
      };
      const vertexShader =
        `
          varying vec2 vUv;
          varying vec3 fNormal;
          varying vec3 vPosition;
          void main()
          {
            vUv = uv;
            fNormal=normal;
            vPosition=position;
            gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
          }
          `
      const fragmentShader =
        `varying vec2 vUv;
          uniform float iTime;
          uniform sampler2D colorTexture;
          vec3 hsb2rgb(const vec3 c) {
          vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0, 4.0, 2.0), 6.0)-3.0)-1.0, 0.0, 1.0);
          rgb = rgb*rgb*(3.0-2.0*rgb);
          return c.z * mix( vec3(1.0), rgb, c.y);
        }
        void main() {
          vec2 uv = vUv;
          vec2 p = 2.0*uv.xy - vec2(1., 1.) ; // center what being drawn
          float r = length(p) * 2.; //圈数量
          vec3 color = hsb2rgb(vec3(0.6, 1., 1.)); //0.24, 0.7, 0.5
          vec4 textureValue = texture2D( colorTexture, vUv );
          float a = pow(r, 2.0); //圈数量
          float b = sin(r * 0.8 - 1.6);
          float c = sin(r - .10);
          float s = sin(a - iTime * 3.0 + b) * c;
          color *= abs(1.0 / (s * 30.)) - 0.1; //初始圈大小
          gl_FragColor = vec4(color, 1.);
        }
        `
      var material = new THREE.ShaderMaterial({
        uniforms: this.uniforms,
        vertexShader: vertexShader,
        fragmentShader: fragmentShader,
        // depthTest: false,
        // depthWrite: false,
        side: THREE.DoubleSide,
        blending: THREE.AdditiveBlending,
        transparent: true,
        opacity: 1
      })
      let plane2 = new THREE.Mesh(geometry2, material);
      // plane2.rotateX(-Math.PI/2)
      plane2.position.y = -0.015
      this.scene.add(plane2);

      let rotatingApertureTexture = new THREE.TextureLoader().load("/static/map/texture/rotating-point2.png")
      let rotatingApertureerial = new THREE.MeshBasicMaterial({
        map: rotatingApertureTexture,
        transparent: true,
        opacity: 1,
        depthTest: true,
        depthWrite: false,
      });
      let rotatingApertureGeometry = new THREE.PlaneBufferGeometry(4.0, 4.0);
      this.rotatingApertureMesh = new THREE.Mesh(rotatingApertureGeometry, rotatingApertureerial);
      // this.rotatingApertureMesh.rotateX(-Math.PI/2)
      this.rotatingApertureMesh.position.x = 0.08
      this.rotatingApertureMesh.scale.set(1.3, 1.3, 1.3);
      this.scene.add(this.rotatingApertureMesh);

      let rotatingPointTexture = new THREE.TextureLoader().load("/static/map/texture/rotating-point2.png")
      let material2 = new THREE.MeshBasicMaterial({
        map: rotatingPointTexture,
        transparent: true,
        opacity: 1,
        depthTest: true,
        depthWrite: false,
      });

      this.rotatingPointMesh = new THREE.Mesh(rotatingApertureGeometry, material2);
      // this.rotatingPointMesh.rotateX(-Math.PI/2)
      this.rotatingPointMesh.position.x = 0.08
      this.rotatingPointMesh.scale.set(1.4, 1.4, 1.4);
      this.scene.add(this.rotatingPointMesh);
    },

    // 地图label
    setMapName() {
      this.map.children.forEach((elem, index) => {
        // 找到中心点
        const y = -elem.properties._centroid[1]
        const x = elem.properties._centroid[0]
        // 转化为二维坐标
        const vector = new THREE.Vector3(x, y, this.mapConfig.deep + 0.01)

        // 添加城市名称
        this.setCityName(vector, elem.properties.name);
      })
    },

    // 获取数据后，加载模型
    getResponseData() {
      let self = this;
      setTimeout(function () {
        self.addCityModel();
        // self.addAlarmModel();
        // self.addEnergyModel();
        self.addMonitorModel();
        self.swaddMonitorModel();
        self.yladdMonitorModel();
        self.szaddMonitorModel();
        // 初始化动画
        setTimeout(self.cameraTween, 1000)
      }, 500)
    },

    // 地区中心点 - 获取向量
    mapElem2Centroid(elem) {
      // 找到中心点
      const y = -elem.properties._centroid[1];
      const x = elem.properties._centroid[0];
      // 转化为二维坐标
      const vector = new THREE.Vector3(x, y, this.mapConfig.deep + 0.01);
      return vector;
    },

    // 数据归一化，映射到0-1区间 - 获取最大值
    getMaxV(distributionInfo) {
      let max = 0;
      for (let item of distributionInfo) {
        if (max < item.total) max = item.total;
      }
      return max;
    },
    // 数据归一化，映射到0-1区间 - 获取最小值
    getMinV(distributionInfo) {
      let min = 1000000;
      for (let item of distributionInfo) {
        if (min > item.total) min = item.total;
      }
      return min;
    },
    // 数据归一化，映射到0-1区间
    normalization(data, min, max) {
      let normalizationRatio = (data - min) / (max - min)
      return normalizationRatio
    },

    // GroupOne 添加模型
    addCityModel() {
      // 数据归一化
      // const min = this.getMinV(this.dataTotal);
      // const max = this.getMaxV(this.dataTotal);
      // console.log(min,max)
      // 添加模型
      this.map.children.forEach((elem, index) => {
        // console.log(elem);
        // 满足数据条件 dataTotal
        // if(this.dataTotal) {
        const vector = this.mapElem2Centroid(elem);
        // this.dataTotal.forEach(d => {
        // 数据归一化，映射到0-1区间
        // let num = this.normalization(d.total, min, max);
        // console.log(d.name ,elem.properties.name);
        // 判断区县
        // if(d.name === elem.properties.name) {

        // 添加城市光波
        // this.setCityWave(vector);

        // 添加城市标记
        this.setCityMarker(vector);

        // 添加城市光柱
        // this.setCityCylinder(vector, 0.3);//0.1 光柱的高度

        // 添加城市数据
        // this.setCityNum(vector, num, d);
        // }
        // })
        this.scene.add(this.groupOne);
        // }
      })
    },

    // GroupTwo 添加模型
    addAlarmModel() {
      this.map.children.forEach((elem, index) => {
        console.log(elem, 123);
        // 满足数据条件 dataAlarm
        if (this.dataAlarm) {
          const vector = this.mapElem2Centroid(elem);
          console.log(vector, 123);
          // 各等级颜色 1、2、3
          const colorLevel = ["#ff1800", "#FF8A00", "#FAE52D"];
          this.dataAlarm.forEach(d => {
            // 判断区县
            // if(d.name === elem.properties.name) {
            // 添加告警光波
            this.setAlarmWave(vector, colorLevel[d.level - 1]);

            // 添加告警标记
            this.setAlarmCylinder(vector, colorLevel[d.level - 1]);

            // 添加告警名称
            this.setAlarmName(vector, colorLevel[d.level - 1], d);
            // }
          })

          // 先隐藏，通过按钮控制
          this.groupTwo.visible = false;
          this.scene.add(this.groupTwo);
        }
      })
    },

    // GroupThree 添加模型
    addEnergyModel() {
      this.map.children.forEach((elem, index) => {
        // console.log(elem);
        // 满足数据条件 dataEnergy
        if (this.dataEnergy) {
          const vector = this.mapElem2Centroid(elem);
          // 各等级颜色 1、2、3
          const colorLevel = ["#ff1800", "#FF8A00", "#FAE52D"];
          this.dataEnergy.forEach(d => {
            // 判断区县
            // if(d.name === elem.properties.name) {
            // 添加能源光波
            this.setEnergyWave(vector, colorLevel[d.level - 1]);

            // 添加能源标记
            this.setEnergyCylinder(vector, colorLevel[d.level - 1]);

            // 添加能源名称
            this.setEnergyName(vector, colorLevel[d.level - 1], d);
            // }
          })

          // 先隐藏，通过按钮控制
          this.groupThree.visible = false;
          this.scene.add(this.groupThree);
        }
      })
    },

    // GroupFour 添加模型（监控）
    addMonitorModel() {
      this.spzData.forEach((elem, index) => {
        console.log(elem);
        // 满足数据条件 dataMonitor
        // if(this.monitorPostionList) {
        const vector = this.mapElem2Centroid(elem);
        console.log(vector);
        // 各等级颜色 1、2、3
        // this.monitorPostionList.forEach(d => {
        // 判断区县
        // if(d.name === elem.properties.name) {
        // 添加监测光波
        this.setMonitorWave(vector);

        // 添加监测标记
        this.setMonitorIcon(vector);

        // 添加监测名称
        this.setMonitorName(vector, elem);
        // }
        // })

        // 先隐藏，通过按钮控制
        this.groupFive.visible = false;
        this.scene.add(this.groupFive);
        // }
      })
    },

    // GroupFour 添加模型（水文）
    swaddMonitorModel() {
      this.swzData.forEach((elem, index) => {
        console.log(elem);
        // 满足数据条件 dataMonitor
        // if(this.monitorPostionList) {
        const vector = this.mapElem2Centroid(elem);
        console.log(vector);
        // 各等级颜色 1、2、3
        // this.monitorPostionList.forEach(d => {
        // 判断区县
        // if(d.name === elem.properties.name) {
        // 添加监测光波
        this.swSetMonitorWave(vector);

        // 添加监测标记
        this.swSetMonitorIcon(vector);

        // 添加监测名称
        this.swSetMonitorName(vector, elem);
        // }
        // })

        // 先隐藏，通过按钮控制
        this.groupsw.visible = false;
        this.scene.add(this.groupsw);
        // }
      })
    },

    // GroupFour 添加模型（雨量）
    yladdMonitorModel() {
      this.ylzData.forEach((elem, index) => {
        console.log(elem);
        // 满足数据条件 dataMonitor
        // if(this.monitorPostionList) {
        const vector = this.mapElem2Centroid(elem);
        console.log(vector);
        // 各等级颜色 1、2、3
        // this.monitorPostionList.forEach(d => {
        // 判断区县
        // if(d.name === elem.properties.name) {
        // 添加监测光波
        this.ylSetMonitorWave(vector);

        // 添加监测标记
        this.ylSetMonitorIcon(vector);

        // 添加监测名称
        this.ylSetMonitorName(vector, elem);
        // }
        // })

        // 先隐藏，通过按钮控制
        this.groupyl.visible = false;
        this.scene.add(this.groupyl);
        // }
      })
    },

    // GroupFour 添加模型（水质）
    szaddMonitorModel() {
      this.szzData.forEach((elem, index) => {
        console.log(elem);
        // 满足数据条件 dataMonitor
        // if(this.monitorPostionList) {
        const vector = this.mapElem2Centroid(elem);
        console.log(vector);
        // 各等级颜色 1、2、3
        // this.monitorPostionList.forEach(d => {
        // 判断区县
        // if(d.name === elem.properties.name) {
        // 添加监测光波
        this.szSetMonitorWave(vector);

        // 添加监测标记
        this.szSetMonitorIcon(vector);

        // 添加监测名称
        this.szSetMonitorName(vector, elem);
        // }
        // })

        // 先隐藏，通过按钮控制
        this.groupsz.visible = false;
        this.scene.add(this.groupsz);
        // }
      })
    },
    // 城市 - 光柱
    setCityCylinder(vector, num) {
      const height = num;
      const geometry = new THREE.CylinderGeometry(0.08, 0.08, height, 20);

      // 顶点着色器
      const vertexShader = `
          uniform vec3 viewVector;
          varying float intensity;
          void main() {
              gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 );
              vec3 actual_normal = vec3(modelMatrix * vec4(normal, 0.0));
              intensity = pow(dot(normalize(viewVector), actual_normal), 3.0);
          }
          `
      // 片段着色器
      const fragmentShader = `
          varying float intensity;
          void main() {
            vec3 glow = vec3(246, 239, 0) * 3.0;
            gl_FragColor = vec4(glow, 1);
          }
          `

      let material = new THREE.MeshPhongMaterial({  // ShaderMaterial
        // uniforms: {
        //     viewVector: this.camera.position
        // },
        // vertexShader: vertexShader,
        // fragmentShader: fragmentShader,
        color: "#ede619",
        side: THREE.FrontSide,
        blending: THREE.AdditiveBlending,
        transparent: true,
        // depthTest: false,
        precision: "mediump",
        // depthFunc: THREE.LessEqualDepth,
        opacity: 0.9,
      });

      const cylinder = new THREE.Mesh(geometry, material);
      cylinder.position.set(vector.x, vector.y, vector.z + height / 2);
      cylinder.rotateX(Math.PI / 2);
      cylinder.scale.set(1, 1, 1);
      // cylinder.position.z -= height / 2;
      // cylinder.translateY(-height);
      cylinder._height = height;

      // 法向量计算位置
      // let coordVec3 = vector.normalize();
      // // mesh默认在XOY平面上，法线方向沿着z轴new THREE.Vector3(0, 0, 1)
      // let meshNormal = new THREE.Vector3(0, 0, 0);
      // // 四元数属性，角度旋转，quaternion表示mesh的角度状态，setFromUnitVectors();计算两个向量之间构成的四元数值
      // cylinder.quaternion.setFromUnitVectors(meshNormal, coordVec3);
      this.cityCylinderMeshArr.push(cylinder);
      this.groupOne.add(cylinder);
      // this.scene.add(cylinder);
    },

    // 城市 - 光波
    setCityWave(vector) {
      const cityGeometry = new THREE.PlaneBufferGeometry(1, 1); //默认在XOY平面上
      const textureLoader = new THREE.TextureLoader(); // TextureLoader创建一个纹理加载器对象
      const texture = textureLoader.load('/static/map/texture/wave.png');

      // 如果不同mesh材质的透明度、颜色等属性同一时刻不同，材质不能共享
      const cityWaveMaterial = new THREE.MeshBasicMaterial({
        color: "#ede619",  // 0x22ffcc
        map: texture,
        transparent: true, //使用背景透明的png贴图，注意开启透明计算
        opacity: 1.0,
        side: THREE.FrontSide, //双面可见
        depthWrite: false, //禁止写入深度缓冲区数据
        blending: THREE.AdditiveBlending,
      });

      let cityWaveMesh = new THREE.Mesh(cityGeometry, cityWaveMaterial);
      cityWaveMesh.position.set(vector.x, vector.y, vector.z);
      cityWaveMesh.size = 0;
      // cityWaveMesh.scale.set(0.1, 0.1, 0.1);  // 设置mesh大小

      // 法向量计算位置
      // let coordVec3 = vector.normalize();
      // // mesh默认在XOY平面上，法线方向沿着z轴new THREE.Vector3(0, 0, 1)
      // let meshNormal = new THREE.Vector3(0, 0, 0);
      // // 四元数属性，角度旋转，quaternion表示mesh的角度状态，setFromUnitVectors();计算两个向量之间构成的四元数值
      // cityWaveMesh.quaternion.setFromUnitVectors(meshNormal, coordVec3);
      this.cityWaveMeshArr.push(cityWaveMesh);
      this.groupOne.add(cityWaveMesh);
      // 添加到场景中
      // this.scene.add(cityWaveMesh);
    },
    setCityMarker(vector) {
      const cityGeometry = new THREE.PlaneBufferGeometry(0.2, 1.5); //默认在XOY平面上
      const textureLoader = new THREE.TextureLoader(); // TextureLoader创建一个纹理加载器对象
      const texture = textureLoader.load('/static/map/texture/光柱.png');
      cityGeometry.rotateX(Math.PI / 2)
      // cityGeometry.translate(0, -1,0)
      // 如果不同mesh材质的透明度、颜色等属性同一时刻不同，材质不能共享
      const cityMaterial = new THREE.MeshBasicMaterial({
        color: "rgb(117,251,253)",  // 0x22ffcc
        map: texture,
        transparent: true, //使用背景透明的png贴图，注意开启透明计算
        // opacity: 1.0,
        side: THREE.FrontSide, //双面可见
        depthWrite: false, //禁止写入深度缓冲区数据
        // blending: THREE.AdditiveBlending,
      });
      cityMaterial.blending = THREE.CustomBlending;
      cityMaterial.blendSrc = THREE.SrcAlphaFactor;
      cityMaterial.blendDst = THREE.DstAlphaFactor;
      cityMaterial.blendEquation = THREE.AddEquation;

      let cityMarkerMesh = new THREE.Mesh(cityGeometry, cityMaterial);
      cityMarkerMesh.position.set(vector.x, vector.y, vector.z);
      cityMarkerMesh.renderOrder = 2
      cityMarkerMesh.name = 'createLightPillar01'
      cityMarkerMesh.size = 0;

      // 光柱02：复制光柱01
      let light02 = cityMarkerMesh.clone()
      light02.position.set(vector.x, vector.y, vector.z);
      light02.renderOrder = 2
      light02.name = 'createLightPillar02'
      // 光柱02，旋转90°，跟 光柱01交叉
      // light02.rotateX(Math.PI / 2)

      // cityWaveMesh.scale.set(0.1, 0.1, 0.1);  // 设置mesh大小

      this.cityMarkerMeshArr.push(cityMarkerMesh);
      this.groupOne.add(cityMarkerMesh, light02);
      // 添加到场景中
      // this.scene.add(cityMarkerMesh);  
    },

    // 城市 - 数据显示
    setCityNum(vector, num, data) {
      // CSS2DRenderer生成的标签直接就是挂在真实的DOM上，并非是Vue的虚拟DOM上
      const div = document.createElement('div');
      div.className = 'city-num-label';
      div.textContent = data.total;

      const contentDiv = document.createElement('div');
      contentDiv.className = 'city-num-label-content';
      contentDiv.innerHTML =
        '本区县共有窑炉企业 ' + data.total + ' 个。<br/>' +
        '介绍：' + data.brief
        ;
      div.appendChild(contentDiv);

      const label = new CSS2DObject(div);
      label.position.set(vector.x, vector.y, num + 0.5);
      label.visible = true;
      this.cityNumMeshArr.push(label);
      this.groupOne.add(label);
      // this.scene.add(spritey);

    },

    // 城市 - 名称显示
    setCityName(vector, name) {
      let spritey = this.makeTextSprite(
        name,
        {
          fontface: "微软雅黑",
          fontsize: 28,  // 定100调整位置，下面通过scale缩放
          fontColor: { r: 255, g: 255, b: 255, a: 1.0 },
          borderColor: { r: 94, g: 94, b: 94, a: 0.0 },
          backgroundColor: { r: 255, g: 255, b: 0, a: 0.0 },
          borderThickness: 2,
          round: 6
        }
      );
      // 轻微偏移，错开光柱
      spritey.position.set(vector.x + 0.06, vector.y + 0.0, 0.22);  // num + 0.3
      this.scene.add(spritey);
    },

    // 城市 - 名称显示 - 小精灵mesh
    makeTextSprite(message, parameters) {
      if (parameters === undefined) parameters = {};

      let fontface = parameters["fontface"];
      let fontsize = parameters["fontsize"];
      let fontColor = parameters["fontColor"];
      let borderThickness = parameters["borderThickness"];
      let borderColor = parameters["borderColor"];
      let backgroundColor = parameters["backgroundColor"];

      // var spriteAlignment = THREE.SpriteAlignment.topLeft;

      let canvas = document.createElement('canvas');
      let context = canvas.getContext('2d');
      context.font = "Bold " + fontsize + "px " + fontface;

      // get size data (height depends only on font size)
      let metrics = context.measureText(message);
      let textWidth = metrics.width;

      // background color
      context.fillStyle = "rgba(" + backgroundColor.r + "," + backgroundColor.g + "," + backgroundColor.b + "," + backgroundColor.a + ")";
      // border color
      context.strokeStyle = "rgba(" + borderColor.r + "," + borderColor.g + "," + borderColor.b + "," + borderColor.a + ")";

      context.lineWidth = borderThickness;
      const painting = {
        width: textWidth * 1.4 + borderThickness * 2,
        height: fontsize * 1.4 + borderThickness * 2,
        round: parameters["round"]
      };
      // 1.4 is extra height factor for text below baseline: g,j,p,q.
      // context.fillRect(0, 0, painting.width, painting.height)
      this.roundRect(
        context,
        borderThickness / 2,
        borderThickness / 2,
        painting.width,
        painting.height,
        painting.round
      );

      // text color
      context.fillStyle = "rgba(" + fontColor.r + "," + fontColor.g + "," + fontColor.b + "," + fontColor.a + ")";
      context.textAlign = "center";
      context.textBaseline = "middle";

      context.fillText(message, painting.width / 2, painting.height / 2);

      // canvas contents will be used for a texture
      let texture = new THREE.Texture(canvas)
      texture.needsUpdate = true;
      let spriteMaterial = new THREE.SpriteMaterial({
        map: texture,
        useScreenCoordinates: false,
        depthTest: false,  // 解决精灵谍影问题
        // blending: THREE.AdditiveBlending,
        // transparent: true,
        // alignment: spriteAlignment
      });
      let sprite = new THREE.Sprite(spriteMaterial);
      sprite.scale.set(1, 1 / 2, 1);
      return sprite;
    },

    // 城市 - 名称显示 - 样式
    roundRect(ctx, x, y, w, h, r) {
      ctx.beginPath();
      ctx.moveTo(x + r, y);
      ctx.lineTo(x + w - r, y);
      ctx.quadraticCurveTo(x + w, y, x + w, y + r);
      ctx.lineTo(x + w, y + h - r);
      ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
      ctx.lineTo(x + r, y + h);
      ctx.quadraticCurveTo(x, y + h, x, y + h - r);
      ctx.lineTo(x, y + r);
      ctx.quadraticCurveTo(x, y, x + r, y);
      ctx.closePath();
      ctx.fill();
      ctx.stroke();
    },

    // 告警 - 光波
    setAlarmWave(vector, color) {
      const geometry = new THREE.PlaneBufferGeometry(1, 1); //默认在XOY平面上
      const textureLoader = new THREE.TextureLoader(); // TextureLoader创建一个纹理加载器对象
      const texture = textureLoader.load('/static/map/texture/alarm.png');

      const material = new THREE.MeshBasicMaterial({
        color: color,
        map: texture,
        transparent: true, //使用背景透明的png贴图，注意开启透明计算
        opacity: 1.0,
        side: THREE.FrontSide,
        depthWrite: false, //禁止写入深度缓冲区数据
        blending: THREE.AdditiveBlending,

      });

      let mesh = new THREE.Mesh(geometry, material);
      mesh.position.set(vector.x, vector.y, vector.z);
      mesh.scale.set(0.4, 0.4, 0.4);  // 设置mesh大小

      this.alarmWaveMeshArr.push(mesh);
      this.groupTwo.add(mesh);
    },

    // 告警 - 三角锥标记
    setAlarmCylinder(vector, color) {
      const geometry = new THREE.CylinderGeometry(0.1, 0.0, 0.3, 3);
      let material = new THREE.MeshPhongMaterial({  // ShaderMaterial
        color: color,
        side: THREE.FrontSide,
        // blending: THREE.AdditiveBlending,
        transparent: true,
        opacity: 0.8,
      });

      const cylinder = new THREE.Mesh(geometry, material);
      cylinder.position.set(vector.x, vector.y, vector.z + 0.3);
      cylinder.rotateX(Math.PI / 2);
      cylinder.scale.set(1, 1, 1);

      this.alarmCylinderMeshArr.push(cylinder);
      this.groupTwo.add(cylinder);
    },

    // 告警 - 名称显示
    setAlarmName(vector, color, data) {
      // CSS2DRenderer生成的标签直接就是挂在真实的DOM上，并非是Vue的虚拟DOM上
      const div = document.createElement('div');
      div.className = 'alarm-label';

      const icon = document.createElement('span');
      icon.className = 'alarm-label-icon';
      icon.textContent = '●';
      icon.style.color = color;
      div.appendChild(icon);

      const text = document.createElement('span');
      text.className = 'alarm-label-text';
      text.textContent = data.type;
      div.appendChild(text);

      const contentDiv = document.createElement('div');
      contentDiv.className = 'alarm-label-content';
      contentDiv.innerHTML =
        '告警：' + data.content + '<br/>' +
        '企业：' + data.company + '<br/>' +
        '位置：' + data.location + '<br/>' +
        '电话：' + data.tel
        ;
      div.appendChild(contentDiv);

      const label = new CSS2DObject(div);
      label.position.set(vector.x, vector.y, vector.z + 0.65);
      label.visible = false;
      this.alarmNameMeshArr.push(label);
      this.groupTwo.add(label);
      // this.scene.add(spritey);

    },

    // 能源 - 光波
    setEnergyWave(vector, color) {
      const geometry = new THREE.PlaneBufferGeometry(1, 1); //默认在XOY平面上
      const textureLoader = new THREE.TextureLoader(); // TextureLoader创建一个纹理加载器对象
      const texture = textureLoader.load('/static/map/texture/alarm.png');

      const material = new THREE.MeshBasicMaterial({
        color: color,
        map: texture,
        transparent: true, //使用背景透明的png贴图，注意开启透明计算
        opacity: 1.0,
        side: THREE.FrontSide,
        depthWrite: false, //禁止写入深度缓冲区数据
        blending: THREE.AdditiveBlending,

      });

      let mesh = new THREE.Mesh(geometry, material);
      mesh.position.set(vector.x, vector.y, vector.z);
      mesh.scale.set(0.4, 0.4, 0.4);  // 设置mesh大小

      this.energyWaveMeshArr.push(mesh);
      this.groupThree.add(mesh);
    },

    // 能源 - 三角锥标记
    setEnergyCylinder(vector, color) {
      const geometry = new THREE.CylinderGeometry(0.1, 0.0, 0.3, 20);
      let material = new THREE.MeshPhongMaterial({  // ShaderMaterial
        color: color,
        side: THREE.FrontSide,
        // blending: THREE.AdditiveBlending,
        transparent: true,
        opacity: 0.8,
      });

      const cylinder = new THREE.Mesh(geometry, material);
      cylinder.position.set(vector.x, vector.y, vector.z + 0.3);
      cylinder.rotateX(Math.PI / 2);
      cylinder.scale.set(1, 1, 1);

      this.energyCylinderMeshArr.push(cylinder);
      this.groupThree.add(cylinder);
    },

    // 能源 - 名称显示
    setEnergyName(vector, color, data) {
      // CSS2DRenderer生成的标签直接就是挂在真实的DOM上，并非是Vue的虚拟DOM上
      const div = document.createElement('div');
      div.className = 'alarm-label';

      const icon = document.createElement('span');
      icon.className = 'alarm-label-icon';
      icon.textContent = '◆';
      icon.style.color = color;
      div.appendChild(icon);

      const text = document.createElement('span');
      text.className = 'alarm-label-text';
      text.textContent = data.type;
      div.appendChild(text);

      const contentDiv = document.createElement('div');
      contentDiv.className = 'alarm-label-content';
      contentDiv.innerHTML =
        '告警：' + data.content + '<br/>' +
        '企业：' + data.company + '<br/>' +
        '位置：' + data.location + '<br/>' +
        '电话：' + data.tel
        ;
      div.appendChild(contentDiv);

      const label = new CSS2DObject(div);
      label.position.set(vector.x, vector.y, vector.z + 0.65);
      label.visible = false;
      this.energyNameMeshArr.push(label);
      this.groupThree.add(label);
      // this.scene.add(spritey);

    },

    // 监测 - 光波
    setMonitorWave(vector) {
      const geometry = new THREE.PlaneBufferGeometry(1, 1); //默认在XOY平面上
      const textureLoader = new THREE.TextureLoader(); // TextureLoader创建一个纹理加载器对象
      const texture = textureLoader.load('/static/map/texture/marker.png');

      const material = new THREE.MeshBasicMaterial({
        color: "#B3FFFF",
        map: texture,
        transparent: true, //使用背景透明的png贴图，注意开启透明计算
        opacity: 0.9,
        side: THREE.FrontSide,
        depthWrite: false, //禁止写入深度缓冲区数据
        // blending: THREE.AdditiveBlending,

      });

      let mesh = new THREE.Mesh(geometry, material);
      mesh.position.set(vector.x, vector.y, vector.z);
      mesh.scale.set(0.4, 0.4, 0.4);  // 设置mesh大小

      this.monitorWaveMeshArr.push(mesh);
      this.groupFive.add(mesh);
    },

    // 监测 - 标记
    setMonitorIcon(vector) {
      const geometry = new THREE.PlaneGeometry(1, 1);
      const texture = new THREE.TextureLoader().load('/static/map/texture/spjkz01.png')
      let material = new THREE.MeshPhongMaterial({
        map: texture,
        side: THREE.DoubleSide,
        transparent: true,
        // blending: THREE.AdditiveBlending,
        opacity: 1,
      });
      const mesh = new THREE.Mesh(geometry, material);
      mesh.position.set(vector.x, vector.y, vector.z + 0.25);
      mesh.rotateX(Math.PI / 4);
      mesh.scale.set(0.3, 0.3, 0.3);
      // mesh.lookAt(this.camera.position)
      console.log(mesh);
      this.monitorIconMeshArr.push(mesh);
      this.groupFive.add(mesh);
    },

    // 监测 - 名称显示
    setMonitorName(vector, data) {
      // CSS2DRenderer生成的标签直接就是挂在真实的DOM上，并非是Vue的虚拟DOM上
      const div = document.createElement('div');
      // div.className = 'alarm-label';

      // const icon = document.createElement('span');
      // icon.className = 'alarm-label-icon';
      // icon.textContent = '◉';
      // icon.style.color = "#ffffff";
      // div.appendChild(icon);

      // const text = document.createElement('span');
      // text.className = 'alarm-label-text';
      // text.textContent = data.name;
      // div.appendChild(text);

      const contentDiv = document.createElement('div');
      contentDiv.className = 'alarm-label-content';
      contentDiv.innerHTML =
        '状态：' + data.status + '<br/>' +
        '位置：' + data.name
        ;
      div.appendChild(contentDiv);

      const label = new CSS2DObject(div);
      label.position.set(vector.x, vector.y, vector.z + 0.65);
      label.visible = false;
      this.monitorNameMeshArr.push(label);
      this.groupFive.add(label);
      // this.scene.add(spritey);

    },

    // 水文 - 光波
    swSetMonitorWave(vector) {
      const geometry = new THREE.PlaneBufferGeometry(1, 1); //默认在XOY平面上
      const textureLoader = new THREE.TextureLoader(); // TextureLoader创建一个纹理加载器对象
      const texture = textureLoader.load('/static/map/texture/marker.png');

      const material = new THREE.MeshBasicMaterial({
        color: "#B3FFFF",
        map: texture,
        transparent: true, //使用背景透明的png贴图，注意开启透明计算
        opacity: 0.9,
        side: THREE.FrontSide,
        depthWrite: false, //禁止写入深度缓冲区数据
        // blending: THREE.AdditiveBlending,

      });

      let mesh = new THREE.Mesh(geometry, material);
      mesh.position.set(vector.x, vector.y, vector.z);
      mesh.scale.set(0.4, 0.4, 0.4);  // 设置mesh大小

      this.swMonitorWaveMeshArr.push(mesh);
      this.groupsw.add(mesh);
    },

    // 水文 - 标记
    swSetMonitorIcon(vector) {
      const geometry = new THREE.PlaneGeometry(1, 1);
      const texture = new THREE.TextureLoader().load('/static/map/texture/swz001.png')
      let material = new THREE.MeshPhongMaterial({
        map: texture,
        // color: "#ffffff",
        side: THREE.DoubleSide,
        // blending: THREE.AdditiveBlending,
        transparent: true,
        opacity: 1,
      });

      const mesh = new THREE.Mesh(geometry, material);
      mesh.position.set(vector.x, vector.y, vector.z + 0.25);
      mesh.rotateX(Math.PI / 4);
      mesh.scale.set(0.3, 0.3, 0.3);
      // mesh.lookAt(this.camera.position)
      console.log(mesh);
      this.swMonitorIconMeshArr.push(mesh);
      this.groupsw.add(mesh);
    },

    // 水文 - 名称显示
    swSetMonitorName(vector, data) {
      // CSS2DRenderer生成的标签直接就是挂在真实的DOM上，并非是Vue的虚拟DOM上
      const div = document.createElement('div');
      // div.className = 'alarm-label';

      // const icon = document.createElement('span');
      // icon.className = 'alarm-label-icon';
      // icon.textContent = '◉';
      // icon.style.color = "#ffffff";
      // div.appendChild(icon);

      // const text = document.createElement('span');
      // text.className = 'alarm-label-text';
      // text.textContent = data.name;
      // div.appendChild(text);

      const contentDiv = document.createElement('div');
      contentDiv.className = 'alarm-label-content';
      contentDiv.innerHTML =
        '状态：' + data.status + '<br/>' +
        '位置：' + data.name
        ;
      div.appendChild(contentDiv);

      const label = new CSS2DObject(div);
      label.position.set(vector.x, vector.y, vector.z + 0.65);
      label.visible = false;
      this.swMonitorNameMeshArr.push(label);
      this.groupsw.add(label);
      // this.scene.add(spritey);

    },

    // 雨量 - 光波
    ylSetMonitorWave(vector) {
      const geometry = new THREE.PlaneBufferGeometry(1, 1); //默认在XOY平面上
      const textureLoader = new THREE.TextureLoader(); // TextureLoader创建一个纹理加载器对象
      const texture = textureLoader.load('/static/map/texture/marker.png');

      const material = new THREE.MeshBasicMaterial({
        color: "#B3FFFF",
        map: texture,
        transparent: true, //使用背景透明的png贴图，注意开启透明计算
        opacity: 0.9,
        side: THREE.FrontSide,
        depthWrite: false, //禁止写入深度缓冲区数据
        // blending: THREE.AdditiveBlending,

      });

      let mesh = new THREE.Mesh(geometry, material);
      mesh.position.set(vector.x, vector.y, vector.z);
      mesh.scale.set(0.4, 0.4, 0.4);  // 设置mesh大小

      this.ylMonitorWaveMeshArr.push(mesh);
      this.groupyl.add(mesh);
    },

    // 雨量 - 标记
    ylSetMonitorIcon(vector) {
      const geometry = new THREE.PlaneGeometry(1, 1);
      const texture = new THREE.TextureLoader().load('/static/map/texture/ylz01.png')
      let material = new THREE.MeshPhongMaterial({
        map: texture,
        // color: "#ffffff",
        side: THREE.DoubleSide,
        // blending: THREE.AdditiveBlending,
        transparent: true,
        opacity: 1,
      });

      const mesh = new THREE.Mesh(geometry, material);
      mesh.position.set(vector.x, vector.y, vector.z + 0.25);
      mesh.rotateX(Math.PI / 4);
      mesh.scale.set(0.3, 0.3, 0.3);
      // mesh.lookAt(this.camera.position)
      console.log(mesh);
      this.ylMonitorIconMeshArr.push(mesh);
      this.groupyl.add(mesh);
    },

    // 雨量 - 名称显示
    ylSetMonitorName(vector, data) {
      // CSS2DRenderer生成的标签直接就是挂在真实的DOM上，并非是Vue的虚拟DOM上
      const div = document.createElement('div');
      // div.className = 'alarm-label';

      // const icon = document.createElement('span');
      // icon.className = 'alarm-label-icon';
      // icon.textContent = '◉';
      // icon.style.color = "#ffffff";
      // div.appendChild(icon);

      // const text = document.createElement('span');
      // text.className = 'alarm-label-text';
      // text.textContent = data.name;
      // div.appendChild(text);

      const contentDiv = document.createElement('div');
      contentDiv.className = 'alarm-label-content';
      contentDiv.innerHTML =
        '状态：' + data.status + '<br/>' +
        '位置：' + data.name
        ;
      div.appendChild(contentDiv);

      const label = new CSS2DObject(div);
      label.position.set(vector.x, vector.y, vector.z + 0.65);
      label.visible = false;
      this.ylMonitorNameMeshArr.push(label);
      this.groupyl.add(label);
      // this.scene.add(spritey);

    },

    // 水质 - 光波
    szSetMonitorWave(vector) {
      const geometry = new THREE.PlaneBufferGeometry(1, 1); //默认在XOY平面上
      const textureLoader = new THREE.TextureLoader(); // TextureLoader创建一个纹理加载器对象
      const texture = textureLoader.load('/static/map/texture/marker.png');

      const material = new THREE.MeshBasicMaterial({
        color: "#B3FFFF",
        map: texture,
        transparent: true, //使用背景透明的png贴图，注意开启透明计算
        opacity: 0.9,
        side: THREE.FrontSide,
        depthWrite: false, //禁止写入深度缓冲区数据
        // blending: THREE.AdditiveBlending,

      });

      let mesh = new THREE.Mesh(geometry, material);
      mesh.position.set(vector.x, vector.y, vector.z);
      mesh.scale.set(0.4, 0.4, 0.4);  // 设置mesh大小

      this.szMonitorWaveMeshArr.push(mesh);
      this.groupsz.add(mesh);
    },

    // 水质 - 标记
    szSetMonitorIcon(vector) {
      const geometry = new THREE.PlaneGeometry(1, 1);
      const texture = new THREE.TextureLoader().load('/static/map/texture/szz01.png')
      let material = new THREE.MeshPhongMaterial({
        map: texture,
        // color: "#ffffff",
        side: THREE.DoubleSide,
        // blending: THREE.AdditiveBlending,
        transparent: true,
        opacity: 1,
      });

      const mesh = new THREE.Mesh(geometry, material);
      mesh.position.set(vector.x, vector.y, vector.z + 0.25);
      mesh.rotateX(Math.PI / 4);
      mesh.scale.set(0.3, 0.3, 0.3);
      // mesh.lookAt(this.camera.position)
      console.log(mesh);
      this.szMonitorIconMeshArr.push(mesh);
      this.groupsz.add(mesh);
    },

    // 水质 - 名称显示
    szSetMonitorName(vector, data) {
      // CSS2DRenderer生成的标签直接就是挂在真实的DOM上，并非是Vue的虚拟DOM上
      const div = document.createElement('div');
      // div.className = 'alarm-label';

      // const icon = document.createElement('span');
      // icon.className = 'alarm-label-icon';
      // icon.textContent = '◉';
      // icon.style.color = "#ffffff";
      // div.appendChild(icon);

      // const text = document.createElement('span');
      // text.className = 'alarm-label-text';
      // text.textContent = data.name;
      // div.appendChild(text);

      const contentDiv = document.createElement('div');
      contentDiv.className = 'alarm-label-content';
      contentDiv.innerHTML =
        '状态：' + data.status + '<br/>' +
        '位置：' + data.name
        ;
      div.appendChild(contentDiv);

      const label = new CSS2DObject(div);
      label.position.set(vector.x, vector.y, vector.z + 0.65);
      label.visible = false;
      this.szMonitorNameMeshArr.push(label);
      this.groupsz.add(label);
      // this.scene.add(spritey);

    },
    // 射线
    setRaycaster() {
      this.raycaster = new THREE.Raycaster();
      this.mouse = new THREE.Vector2();
      this.tooltip = document.getElementById('tooltip');
      const onMouseMove = (event) => {
        this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
        this.tooltip.style.left = event.clientX + 2 + 'px';
        this.tooltip.style.top = event.clientY + 2 + 'px';
      }

      // 点击地图事件
      const onClick = (event) => {
        // console.log(this.lastPick);
        if (this.lastPick && "point" in this.lastPick) this.mapClickTween(this.lastPick.point);
        else this.resetCameraTween();
      }

      window.addEventListener('mousemove', onMouseMove, false);
      window.addEventListener('click', onClick, false);

    },

    // 鼠标悬浮显示
    showTip() {
      // 显示省份的信息
      // if (this.lastPick) {
      //   const properties = this.lastPick.object.parent.properties;

      //   this.tooltip.textContent = properties.name;

      //   this.tooltip.style.visibility = 'visible';
      // } else {
      //   this.tooltip.style.visibility = 'hidden';
      // }
    },

    // 窗口变化
    onWindowSize() {
      // let container = document.getElementById("container");
      this.camera.aspect = this.container.clientWidth / this.container.clientHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
      this.labelRenderer.setSize(this.container.clientWidth, this.container.clientHeight);
    },

    // Tween - 城市光柱动画
    cityCylinderTween() {
      this.cityCylinderMeshArr.forEach(mesh => {
        // console.log(mesh);
        const begin = {
          z: mesh.position.z,
        };
        const end = {
          z: mesh.position.z + mesh._height,
        };
        const self = this;
        this.$tween.use({
          begin,
          end,
          time: 1000,
          onUpdate(obj) {
            mesh.position.z = obj.z;
          },
          onComplete() {
            // 动画结束，显示数据
            self.cityNumMeshArr.forEach(e => {
              e.visible = true;
            })
            // console.log(document.getElementsByClassName("city-num-label"));
            // for (let i = 0; i < document.getElementsByClassName("city-num-label").length; i++) {
            //   document.getElementsByClassName("city-num-label")[i].style.display = "block"
            // }
          }
        });
      })
    },

    // Tween - 加载时相机移动动画
    cameraTween(i) {
      // console.log("cameraTween");

      !i ? i = 0 : i = i;
      if (i > this.cameraPosArr.length - 1) {
        // this.cityCylinderTween();
        return false;
      }

      //关闭控制器
      this.controller.enabled = false;

      const begin = {
        x: this.camera.position.x,
        y: this.camera.position.y,
        z: this.camera.position.z,
      };
      const end = {
        x: this.cameraPosArr[i].x,
        y: this.cameraPosArr[i].y,
        z: this.cameraPosArr[i].z,
        // x: 0,
        // y: -3.0,
        // z: 3.8,
      };
      const self = this;
      this.$tween.use({
        begin,
        end,
        time: 1500,
        onUpdate(obj) {
          self.camera.position.x = obj.x;
          self.camera.position.y = obj.y;
          self.camera.position.z = obj.z;

          // self.controller.target.x = obj.x;
          // self.controller.target.y = obj.y;
          // self.controller.target.z = obj.z;

          // 控制器更新
          self.controller.update();
        },
        onComplete() {
          self.controller.enabled = true;
          self.cameraTween(i + 1);
        }
      });
    },

    // Tween - 点击省份动画
    mapClickTween(pos) {
      //关闭控制器
      this.controller.enabled = false;

      const begin = {
        x: this.camera.position.x,
        y: this.camera.position.y,
        z: this.camera.position.z,
      };
      const end = {
        x: pos.x,
        y: pos.y,
        z: pos.z + 2.5,
      };
      const self = this;
      this.$tween.use({
        begin,
        end,
        time: 500,
        onUpdate(obj) {
          self.camera.position.x = obj.x;
          self.camera.position.y = obj.y;
          self.camera.position.z = obj.z;

          self.camera.lookAt(obj.x, obj.y, obj.z);

          // 控制器更新
          self.controller.update();
        },
        onComplete() {
          self.controller.enabled = true;
        }
      });
    },

    // Tween - 重置相机
    resetCameraTween() {
      //关闭控制器
      this.controller.enabled = false;

      const begin = {
        x: this.camera.position.x,
        y: this.camera.position.y,
        z: this.camera.position.z,
      };
      const end = {
        x: this.cameraPosArr[this.cameraPosArr.length - 1].x,
        y: this.cameraPosArr[this.cameraPosArr.length - 1].y,
        z: this.cameraPosArr[this.cameraPosArr.length - 1].z,
      };
      const self = this;
      this.$tween.use({
        begin,
        end,
        time: 500,
        onUpdate(obj) {
          self.camera.position.x = obj.x;
          self.camera.position.y = obj.y;
          self.camera.position.z = obj.z;

          self.camera.lookAt(0, 0, 0);

          // 控制器更新
          self.controller.update();
        },
        onComplete() {
          self.controller.enabled = true;
        }
      });
    },

    // 动画
    animate() {
      if (this.rotatingApertureMesh) {
        this.rotatingApertureMesh.rotation.z += 0.0035;
      }
      if (this.rotatingPointMesh) {
        this.rotatingPointMesh.rotation.z -= 0.0035;
      }
      const timer = this.clock.getDelta();
      this.uniforms.iTime.value += Math.sin(timer) / 3;
      if (this.uniforms.iTime.value > 1.0) {
        this.uniforms.iTime.value = 0.0;
      }
      requestAnimationFrame(this.animate);

      this.showTip();
      this.animationMouseover();

      // city
      this.animationCityWave();
      this.animationCityMarker();
      this.animationCityCylinder();
      this.animationCityEdgeLight();

      // alarm
      this.animationAlarmWave();
      this.animationAlarmCylinder();

      // energy
      this.animationEnergyWave();

      // monitor
      this.animationMonitorWave();

      this.swanimationMonitorWave();
      this.ylanimationMonitorWave();
      this.szanimationMonitorWave();

      this.controller.update();
      this.renderer.render(this.scene, this.camera);
      this.labelRenderer.render(this.scene, this.camera);
    },

    // 动画 - 鼠标悬浮动作
    animationMouseover() {
      // console.log(111111);
      // 通过摄像机和鼠标位置更新射线
      this.raycaster.setFromCamera(this.mouse, this.camera)
      // 计算物体和射线的焦点，与当场景相交的对象有那些
      const intersects = this.raycaster.intersectObjects(
        this.scene.children,
        true  // true，则同时也会检测所有物体的后代
      )
      // 恢复上一次清空的
      if (this.lastPick) {
        // this.lastPick.object.material[0].color.set('#4161ff');
        this.lastPick.object.material[0].color.set('#ffffff');
        // this.lastPick.object.material[1].color.set('#00035d');
        this.lastPick.object.material[1].color.set('#ffffff');
      }
      this.lastPick = null;
      this.lastPick = intersects.find(
        (item) => item.object.material && item.object.material.length === 2  // 选择map object
      )
      if (this.lastPick) {
        this.lastPick.object.material[0].color.set('#ffcc00');
        // this.lastPick.object.material[1].color.set('#ffcc00');
      }
    },

    // 动画 - 城市光柱
    animationCityCylinder() {

      this.cityCylinderMeshArr.forEach(mesh => {
        // console.log(mesh);

        // 着色器动作
        // let viewVector = new THREE.Vector3().subVectors(this.camera.position, mesh.getWorldPosition());
        // mesh.material.uniforms.viewVector.value = this.camera.position;

        // mesh.translateY(0.05);
        // mesh.position.z <= mesh._height * 2 ? mesh.position.z += 0.05 : "";

        // mesh.scale.z <= 1 ? mesh.scale.z += 0.05 : "";

      })
    },

    // 动画 - 城市光波
    animationCityWave() {
      // console.log(this.cityWaveMesh);
      this.cityWaveMeshArr.forEach(mesh => {
        // console.log(mesh);
        mesh.size += 0.005;  // Math.random() / 100 / 2
        let scale = mesh.size / 1;
        mesh.scale.set(scale, scale, scale);
        if (mesh.size <= 0.5) {
          mesh.material.opacity = 1;
        } else if (mesh.size > 0.5 && mesh.size <= 1) {
          mesh.material.opacity = 1.0 - (mesh.size - 0.5) * 2;  // 0.5以后开始加透明度直到0
        } else if (mesh.size > 1 && mesh.size < 2) {
          mesh.size = 0;
        }
      })
    },
    // 动画 - 城市标记
    animationCityMarker() {
      this.cityMarkerMeshArr.forEach(mesh => {
        // console.log(mesh);
        mesh.rotation.z += 0.05;
      })
    },
    // 动画 - 城市边缘流光
    animationCityEdgeLight() {
      if (this.mapEdgeLightObj.lightOpacitys && this.mapEdgeLightObj.mapEdgePoints) {
        if (this.mapEdgeLightObj.lightCurrentPos > this.mapEdgeLightObj.mapEdgePoints.length) {
          this.mapEdgeLightObj.lightCurrentPos = 0;
        }

        this.mapEdgeLightObj.lightCurrentPos += this.mapEdgeLightObj.lightSpeed;
        for (let i = 0; i < this.mapEdgeLightObj.lightSpeed; i++) {
          this.mapEdgeLightObj.lightOpacitys[(this.mapEdgeLightObj.lightCurrentPos - i) % this.mapEdgeLightObj.mapEdgePoints.length] = 0;
        }

        for (let i = 0; i < 100; i++) {
          this.mapEdgeLightObj.lightOpacitys[(this.mapEdgeLightObj.lightCurrentPos + i) % this.mapEdgeLightObj.mapEdgePoints.length] = i / 50 > 2 ? 2 : i / 50;
        }

        if (this.mapEdgeLightObj.lightOpacityGeometry) {
          this.mapEdgeLightObj.lightOpacityGeometry.attributes.aOpacity.needsUpdate = true;
        }
      }
    },

    // 动画 - 告警光波
    animationAlarmWave() {
      // console.log(this.alarmWaveMeshArr);
      this.alarmWaveMeshArr.forEach(mesh => {
        // console.log(mesh);
        mesh.rotation.z -= 0.01;
      })
    },

    // 动画 - 告警三角锥
    animationAlarmCylinder() {
      this.alarmCylinderMeshArr.forEach(mesh => {
        // console.log(mesh);
        mesh.rotation.y += 0.03;

        // if(mesh.position.z < 0.8) {
        //   mesh.position.z += 0.03;
        // } else if(mesh.position.z > 1.2) {
        //   mesh.position.z -= 0.03;
        // }
      })
    },

    // 动画 - 能源光波
    animationEnergyWave() {
      this.energyWaveMeshArr.forEach(mesh => {
        // console.log(mesh);
        mesh.rotation.z -= 0.01;
      })
    },

    // 动画 - 监测光波
    animationMonitorWave() {
      this.monitorWaveMeshArr.forEach(mesh => {
        // console.log(mesh);
        mesh.rotation.z += 0.03;
      })
    },

    // 动画 - 水文光波
    swanimationMonitorWave() {
      this.swMonitorWaveMeshArr.forEach(mesh => {
        // console.log(mesh);
        mesh.rotation.z += 0.03;
      })
    },

    // 动画 - 雨量光波
    ylanimationMonitorWave() {
      this.ylMonitorWaveMeshArr.forEach(mesh => {
        // console.log(mesh);
        mesh.rotation.z += 0.03;
      })
    },
    // 动画 - 水质光波
    szanimationMonitorWave() {
      this.szMonitorWaveMeshArr.forEach(mesh => {
        // console.log(mesh);
        mesh.rotation.z += 0.03;
      })
    },

    // 切换监控形态
    groupOneChange() {
      // CSS2DObject数据单独做处理
      this.monitorNameMeshArr.forEach(e => { e.visible = true });//监控
      this.swMonitorNameMeshArr.forEach(e => { e.visible = false });//水文
      this.ylMonitorNameMeshArr.forEach(e => { e.visible = false });//雨量
      this.szMonitorNameMeshArr.forEach(e => { e.visible = false });//水质

      this.groupFive.visible = true;
      this.groupsw.visible = false;
      this.groupyl.visible = false;
      this.groupsz.visible = false;

    },
    // 切换水文形态
    groupTwoChange() {
      console.log("groupTwoChange");
      // CSS2DObject数据单独做处理
      this.monitorNameMeshArr.forEach(e => { e.visible = false });//监控
      this.swMonitorNameMeshArr.forEach(e => { e.visible = true });//水文
      this.ylMonitorNameMeshArr.forEach(e => { e.visible = false });//雨量
      this.szMonitorNameMeshArr.forEach(e => { e.visible = false });//水质

      this.groupFive.visible = false;
      this.groupsw.visible = true;
      this.groupyl.visible = false;
      this.groupsz.visible = false;
    },
    // 切换水位形态
    groupThreeChange() {
      this.monitorNameMeshArr.forEach(e => { e.visible = false });//监控
      this.swMonitorNameMeshArr.forEach(e => { e.visible = false });//水文
      this.ylMonitorNameMeshArr.forEach(e => { e.visible = false });//雨量
      this.szMonitorNameMeshArr.forEach(e => { e.visible = false });//水质

      this.groupFive.visible = false;
      this.groupsw.visible = false;
      this.groupyl.visible = false;
      this.groupsz.visible = false;

    },
    // 切换雨量形态
    groupFourChange() {
      this.monitorNameMeshArr.forEach(e => { e.visible = false });//监控
      this.swMonitorNameMeshArr.forEach(e => { e.visible = false });//水文
      this.ylMonitorNameMeshArr.forEach(e => { e.visible = true });//雨量
      this.szMonitorNameMeshArr.forEach(e => { e.visible = false });//水质

      this.groupFive.visible = false;
      this.groupsw.visible = false;
      this.groupyl.visible = true;
      this.groupsz.visible = false;
    },
    // 切换水质形态
    groupFiveChange() {
      this.monitorNameMeshArr.forEach(e => { e.visible = false });//监控
      this.swMonitorNameMeshArr.forEach(e => { e.visible = false });//水文
      this.ylMonitorNameMeshArr.forEach(e => { e.visible = false });//雨量
      this.szMonitorNameMeshArr.forEach(e => { e.visible = true });//水质

      this.groupFive.visible = false;
      this.groupsw.visible = false;
      this.groupyl.visible = false;
      this.groupsz.visible = true;
    }
  }
};
</script>

<style lang="scss">
#container {
  position: absolute;
  width: 100%;
  height: 100%;
}

#tooltip {
  position: absolute;
  z-index: 2;
  background: linear-gradient(180deg, #B0DEFF 0%, #2C4FDC 100%);
  padding: 6px 10px;
  color: #fff;
  border: 2px solid #FAE52D;
  font-weight: bold;
  font-size: 16px;
  /* border-radius: 4px; */
  visibility: hidden;
}

#cityName {
  z-index: 2;
}

.title {
  position: absolute;
  left: 0;
  top: 0;
  box-sizing: border-box;
  z-index: 2;
  width: 100%;
  height: 14%;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  border-bottom: 1px solid #057FE5;
  color: #fff;
  padding: 0 40px;
  padding-bottom: 10px;
}

.title .biaoti {
  font-size: 29px;
  font-weight: 400;
  font-style: italic;
}

.title .time {
  font-size: 20px;
  font-weight: 400;
}

.center {
  position: absolute;
  top: 16%;
  left: 0;
  width: 100%;
  box-sizing: border-box;
  padding: 0 415px;
  // height: 30px;
  display: flex;
  justify-content: space-between;
  color: #fff;

  .center_zhuy {
    display: flex;
    align-items: center;
    font-size: 13px;
    margin-left: 15px;

    .center_zhuy_j {
      width: 80px;
      border: 1px solid #59AFF9;
      background-color: #012376;
      border-radius: 4px;
      padding: 4px 0;
      margin-right: 15px;
      cursor: pointer;
    }

    .center_zhuy_f {
      width: 80px;
      border: 1px solid #59AFF9;
      background-color: #012376;
      border-radius: 4px;
      padding: 4px 0;
      cursor: pointer;
    }
  }

  .center_site {
    display: flex;
    align-items: center;

    .site_item {
      display: flex;
      flex-direction: column;
      margin-right: 60px;
      cursor: pointer;

      .site_item_top {
        display: flex;
        align-items: center;
        font-size: 14px;
        font-weight: 400;
        color: #4386CD;
        margin-bottom: 7px;

        .img {
          width: 32px;
          height: 32px;
          margin-right: 5px;
        }
      }

      .site_item_bottom {
        display: flex;
        justify-content: right;
        align-items: flex-end;
        font-size: 12px;
        font-weight: 400;
        color: #4386CD;

        .site_place {
          font-size: 28px;
          font-weight: bold;
          color: #FFFFFF;
          margin-right: 5px;
        }

        .site_font {
          padding: 4px 0;
        }
      }
    }
  }
}

.center_left {
  position: absolute;
  top: 16%;
  left: 40px;
  width: 375px;
  box-sizing: border-box;

  .yuan {
    width: 4px;
    height: 4px;
    background-color: #57A9F0;
    border-radius: 50%;
  }

  .jyltj {
    margin-bottom: 20px;

    .jyltj_top {
      width: 345px;
      height: 30px;
      background: linear-gradient(to left, #000 0%, #012376 20%, #012376 80%, #000 100%);
      display: flex;
      justify-content: space-between;
      align-items: center;
      color: #fafafa;
      font-size: 13px;
      font-weight: 400;
      padding: 0 15px;

      .titles {
        display: flex;
        align-items: center;

        .imgs {
          width: 13px;
          height: 14px;
          margin-right: 5px;
        }
      }
    }

    .jyltj_center {
      width: 100%;
      height: 150px;
      background: linear-gradient(to bottom, #000 0%, #000d2a 100%);
      display: flex;
      align-items: center;
      justify-content: space-around;

      .jyltj_center_item {
        width: 100px;

        .item_img {
          position: relative;

          .imgs {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
          }

          .img {
            -webkit-animation: rotation 8s linear infinite;
            animation: rotation 8s linear infinite;
          }
        }

        .leiji {
          font-size: 13px;
          font-weight: 400;
          color: #4386CD;
          margin-top: 13px;
        }

        .jyl {
          display: flex;
          align-items: flex-end;
          justify-content: center;
          font-size: 24px;
          font-weight: bold;
          color: #CDD5E5;

          .shuzhi {
            font-size: 14px;
            font-weight: 400;
            color: #4386CD;
            padding-bottom: 4px;
          }
        }
      }

      .shux {
        width: 1px;
        height: 67px;
        background-color: #3A7CC7;
        opacity: 0.3;
      }
    }

    .sssq_center {
      width: 100%;
      height: 210px;
      background: linear-gradient(to bottom, #000 0%, #000d2a 100%);
    }

    .lsltj_center {
      width: 100%;
      height: 210px;
      background: linear-gradient(to bottom, #000 0%, #000d2a 100%);
    }

    .bottom {
      width: 100%;
      height: 1px;
      background: linear-gradient(to left, #000 0%, #057FE5 20%, #057FE5 80%, #000 100%);
    }
  }
}

.center_right {
  position: absolute;
  top: 16%;
  right: 40px;
  width: 375px;
  box-sizing: border-box;

  .yuan {
    width: 4px;
    height: 4px;
    background-color: #57A9F0;
    border-radius: 50%;
  }

  .jyltj {
    margin-bottom: 20px;

    .jyltj_top {
      width: 345px;
      height: 30px;
      background: linear-gradient(to left, #000 0%, #012376 20%, #012376 80%, #000 100%);
      display: flex;
      justify-content: space-between;
      align-items: center;
      color: #fafafa;
      font-size: 13px;
      font-weight: 400;
      padding: 0 15px;

      .titles {
        display: flex;
        align-items: center;

        .imgs {
          width: 13px;
          height: 14px;
          margin-right: 5px;
        }
      }
    }

    .jyltj_center {
      width: 100%;
      height: 150px;
      background: linear-gradient(to bottom, #000 0%, #000d2a 100%);
      box-sizing: border-box;
      padding: 20px 26px;
      display: flex;
      flex-direction: column;
      justify-content: space-between;

      .jyltj_center_item {
        display: flex;
        align-items: center;

        .items {
          flex: 1;
          display: flex;
          align-items: center;

          .img {
            width: 40px;
            height: 42px;
          }

          .items_right {
            display: flex;
            flex-direction: column;
            justify-content: space-around;
            margin-left: 13px;

            .items_title {
              font-size: 13px;
              font-weight: 400;
              color: #4386CD;
            }

            .items_chu {
              display: flex;
              align-items: center;
              justify-content: center;
              font-size: 18px;
              font-weight: bold;
              color: #CDD5E5;

              .items_chu_s {
                font-size: 12px;
                font-weight: 400;
                color: #4386CD;
                padding-bottom: 2px;
                margin-left: 8px;
              }
            }
          }
        }
      }
    }

    .ssszdbqk_center {
      width: 100%;
      height: 210px;
      background: linear-gradient(to bottom, #000 0%, #000d2a 100%);

      .chart-container {
        position: relative;
        width: 100%;
        height: 100%;

        .chart {
          z-index: 1;
        }

        .chart,
        .bg {
          width: 100%;
          height: 100%;
        }

        .bg {
          position: absolute;
          bottom: 40px;
          left: 34%;
          z-index: 0;
          width: 180px;
          height: 73px;
          background: no-repeat center;
          background-image: url('../assets/dizuo.png');
          background-size: 100% 100%;
          transform: translateX(-50%);
        }
      }
    }

    .szbhqs_center {
      width: 100%;
      height: 210px;
      background: linear-gradient(to bottom, #000 0%, #000d2a 100%);
      box-sizing: border-box;
      padding: 15px 10px;

      .inputs {
        width: 40%;
        height: 25px;
      }
    }

    .bottom {
      width: 100%;
      height: 1px;
      background: linear-gradient(to left, #000 0%, #057FE5 20%, #057FE5 80%, #000 100%);
    }
  }
}

@keyframes rotation {
  0% {
    -webkit-transform: rotate(360deg);
  }

  100% {
    -webkit-transform: rotate(0deg);
  }
}

.button-group {
  position: absolute;
  left: 24px;
  top: 24px;
  z-index: 2;
}

/* 城市统计数据 */
.city-num-label {
  width: 32px;
  height: 32px;
  line-height: 32px;
  font-size: 16px;
  font-weight: bold;
  color: #ffffff;
  border-radius: 100px;
  background-color: rgba(192, 174, 12, 0.8);
  box-shadow: 0px 0px 4px rgba(237, 230, 25, 0.5);
  border: 2px solid rgba(237, 230, 25, 1);
  /* font-family: 'PingFang SC'; */
  text-align: center;
  cursor: pointer;
  /* opacity: 0.8; */
  transition: all 0.1s linear;
}

.city-num-label:hover {
  margin-top: -60px;
  width: 300px;
  min-height: 140px;
  padding: 16px 16px;
  text-align: left;
  /* opacity: 1.0; */
  border-radius: 4px;
  box-shadow: 0px 0px 12px rgba(237, 230, 25, 0.9);
}

.city-num-label-content {
  display: none;
  font-size: 12px;
  line-height: 24px;
  color: #eeeeee;
}

.city-num-label:hover .city-num-label-content {
  display: block;
}

/* 告警名称 */
.alarm-label {
  min-width: 100px;
  height: 32px;
  line-height: 30px;
  border-radius: 4px;
  background: rgba(10, 26, 52, 0.8);
  border: 1px solid #59AFF9;
  box-shadow: 0px 0px 4px rgba(3, 149, 255, 0.5);
  text-align: center;
  cursor: pointer;
  transition: all 0.1s linear;
}

.alarm-label:hover {
  margin-top: -60px;
  width: 300px;
  min-height: 140px;
  padding: 16px 16px;
  text-align: left;
  /* opacity: 1.0; */
  box-shadow: 0px 0px 12px rgba(3, 149, 255, 0.9);
}

.alarm-label-icon {
  margin-right: 4px;
  font-size: 22px;
}

.alarm-label-text {
  font-size: 16px;
  font-weight: bold;
  color: #ffffff;
}

.alarm-label-content {
  display: none;
  font-size: 12px;
  line-height: 24px;
  color: #eeeeee;
}

.alarm-label:hover .alarm-label-content {
  display: block;
}
</style>